Raw File
Population.h
/*
  This file is part of the FRED system.

  Copyright (c) 2010-2015, University of Pittsburgh, John Grefenstette,
  Shawn Brown, Roni Rosenfield, Alona Fyshe, David Galloway, Nathan
  Stone, Jay DePasse, Anuroop Sriram, and Donald Burke.

  Licensed under the BSD 3-Clause license.  See the file "LICENSE" for
  more information.
*/

//
//
// File: Population.h
//

#ifndef _FRED_POPULATION_H
#define _FRED_POPULATION_H

#include <fstream>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <sstream>
#include <stdio.h>
#include <string>
#include <vector>
#include "Bloque.h"
#include "Demographics.h"
#include "Global.h"
#include "Utils.h"

using namespace std;

class Person;
class Disease;
class Antivirals;
class AV_Manager;
class Vaccine_Manager;
class Place;



class Person_Init_Data;

class Population {

public:

  /**
   * Default constructor
   */
  Population();
  ~Population();

  void initialize_masks();

  /**
   * Sets the static variables for the class from the parameter file.
   */
  void get_parameters();

  /**
   * Prepare this Population (calls read_population)
   * @see Population::read_population()
   */
  void setup();

  /**
   * Used during debugging to verify that code is functioning properly.
   */
  void quality_control();

  /**
   * Perform end of run operations (clean up)
   */
  void end_of_run();

  /**
   * Perform beginning of day operations
   * @param day the simulation day
   */
  void update(int day);

  /**
   * Report the disease statistics for a given day
   * @param day the simulation day
   */
  void report(int day);

  /**
   * @return the pop_size
   */
  int get_pop_size() {
    return this->pop_size;
  }

  //Mitigation Managers
  /**
   * @return a pointer to this Population's AV_Manager
   */
  AV_Manager* get_av_manager(){
    return this->av_manager;
  }

  /**
   * @return a pointer to this Population's Vaccine_Manager
   */
  Vaccine_Manager* get_vaccine_manager() {
    return this->vacc_manager;
  }

  /**
   * @param args passes to Person ctor; all persons added to the
   * Population must be created through this method
   *
   * @return pointer to the person created and added
   */
  Person* add_person(int age, char sex, int race, int rel, Place* house,
		     Place* school, Place* work, int day, bool today_is_birthday);

  /**
   * @param per a pointer to the Person to remove from the Population
   */
  void delete_person(Person* per);

  /**
   * Perform the necessary steps for an agent's death
   * @param day the simulation day
   * @param person the agent who will die
   */
  void prepare_to_die(int day, Person* person);

  void remove_dead_from_population(int day);

  void remove_dead_person_from_population(int day, Person *person);

  /**
   * @param index the index of the Person
   * Return a pointer to the Person object at this index
   */
  Person* get_person_by_index(int index);

  size_t get_index_size() {
    return this->blq.get_index_size();
  }

  /**
   * @param n the id of the Person
   * Return a pointer to the Person object with this id
   */
  Person* get_person_by_id(int id);

  // Modifiers on the entire pop;
  // void apply_residual_immunity(Disease* disease) {}

  /**
   * Assign agents in Schools to specific Classrooms within the school
   */
  void assign_classrooms();

  /**
   * Assign agents in Workplaces to specific Offices within the workplace
   */
  void assign_offices();

  /**
   * Assign all agents a primary healthcare facility
   */
  void assign_primary_healthcare_facilities();

  /**
   * Write degree information to a file degree.txt
   * @param directory the directory where the file will be written
   */
  void get_network_stats(char* directory);

  void split_synthetic_populations_by_deme();

  void read_all_populations();

  void read_population(const char* pop_dir, const char* pop_id, const char* pop_type );

  /**
   *
   */
  void print_age_distribution(char* dir, char* date_string, int run);

  /**
   * @return a pointer to a random Person in this population
   */
  Person* select_random_person();

  /**
   * @return a pointer to a random Person in this population
   * whose age is in the given range
   */
  Person* select_random_person_by_age(int min_age, int max_age);

  /*
   * Set the mask bit for the person_index
   *
   * TODO redefine the mask type so that multiple sets of masks
   * are available (one set for each disease)
   */
  void set_mask_by_index(fred::Pop_Masks mask, int person_index);

  /*
   * Clear the mask bit for the person_index
   *
   * TODO redefine the mask type so that multiple sets of masks
   * are available (one set for each disease)
   */
  void clear_mask_by_index(fred::Pop_Masks mask, int person_index);

  /*
   * Check to see if mask is set for person_index
   */
  bool check_mask_by_index(fred::Pop_Masks mask, int person_index) {
    return this->blq.mask_is_set( mask, person_index );
  }

  void set_school_income_levels();
  void report_mean_hh_income_per_school();
  void report_mean_hh_size_per_school();
  void report_mean_hh_distance_from_school();
  void report_mean_hh_stats_per_income_category();
  void report_mean_hh_stats_per_census_tract();
  void report_mean_hh_stats_per_income_category_per_census_tract();

  //  //TODO REMOVE
  //  void print_HAZEL_data();
  
  int size() {
    assert(this->blq.size() == this->pop_size);
    return this->blq.size();
  }

  int size(fred::Pop_Masks mask) {
    return this->blq.size(mask);
  }

  void get_age_distribution(int* count_males_by_age, int* count_females_by_age);

  template<typename Functor>
  void apply(Functor &f) {
    this->blq.apply(f);
  }

  template<typename Functor>
  void apply(fred::Pop_Masks m, Functor &f) {
    this->blq.apply(m, f);
  }

  template<typename Functor>
  void parallel_apply(Functor &f) {
    this->blq.parallel_apply(f);
  }

  template<typename Functor>
  void parallel_masked_apply(fred::Pop_Masks m, Functor &f) {
    this->blq.parallel_masked_apply(m, f);
  }

  template<typename Functor>
  void parallel_not_masked_apply(fred::Pop_Masks m, Functor &f) {
    this->blq.parallel_not_masked_apply(m, f);
  }

  const std::vector<Utils::Tokens> &get_demes() {
    return this->demes;
  }
  /* TODO rewrite
     template< typename MaskType >
     struct masked_iterator : bloque< Person, fred::Pop_Masks >::masked_iterator< MaskType > { };

     template< typename MaskType >
     masked_iterator< MaskType > begin() { return blq.begin(); }

     template< typename MaskType >
     masked_iterator< MaskType > end() { return blq.end(); }
  */

  void update_infectious_people(int day);

  void add_susceptibles_to_infectious_places(int day);

  void add_visitors_to_infectious_places(int day);

  void initialize_demographic_dynamics();

  void update_traveling_people(int day);

  bool is_load_completed() {
    return this->load_completed;
  }

private:

  bool load_completed;

  void mother_gives_birth(int day, Person* mother);

  struct PopFileColIndex {
    // all populations
    static const int p_id = 0;
    static const int home_id = 1; // <-- this is either hh_id or gq_id
    int sporder;
    int age_str;
    int sex_str;
    int workplace_id; // <-- same as home_id for gq pop
    int number_of_columns;
    // only synth_people population
    int serial_no;
    int stcotrbg;
    int race_str;
    int relate;
    int school_id;
    // only synth_gq_people population
    int gq_type;
  };

  struct HH_PopFileColIndex : PopFileColIndex {
    HH_PopFileColIndex() {
      serial_no = 2;
      stcotrbg = 3;
      age_str = 4;
      sex_str = 5;
      race_str = 6;
      sporder = 7;
      relate = 8;
      school_id = 9;
      workplace_id = 10;
      number_of_columns = 11;
    }
  } hh_pop_file_col_index;

  struct GQ_PopFileColIndex : PopFileColIndex {
    GQ_PopFileColIndex() {
      gq_type = 2;
      sporder = 3;
      age_str = 4;
      sex_str = 5;
      workplace_id = 1; // <-- same as home_id
      number_of_columns = 6;
    }
  } gq_pop_file_col_index;

  struct GQ_PopFileColIndex_2010_ver1 : PopFileColIndex {
    GQ_PopFileColIndex_2010_ver1() {
      sporder = 2;
      age_str = 3;
      sex_str = 4;
      workplace_id = 1; // <-- same as home_id
      number_of_columns = 5;
    }
  } gq_pop_file_col_index_2010_ver1;

  const PopFileColIndex &get_pop_file_col_index(bool is_group_quarters, bool is_2010_ver1) const {
    if(is_group_quarters) {
      if(is_2010_ver1) {
	return this->gq_pop_file_col_index_2010_ver1;
      } else {
	return this->gq_pop_file_col_index;
      }
    } else {
      return this->hh_pop_file_col_index;
    }
  }

  std::vector<Utils::Tokens> demes;

  void parse_lines_from_stream(std::istream &stream, bool is_group_quarters_pop);

  Person_Init_Data get_person_init_data(char* line,
					bool is_group_quarters_population,
					bool is_2010_ver1_format);


  bloque<Person, fred::Pop_Masks> blq;   // all Persons in the population
  vector<Person*> death_list;		  // list of agents to die today
  int pop_size;

  int enable_copy_files;
    
  static char profilefile[FRED_STRING_SIZE];
  static char pop_outfile[FRED_STRING_SIZE];
  static char output_population_date_match[FRED_STRING_SIZE];
  static int output_population;
  static bool is_initialized;
  static int next_id;

  //Mitigation Managers
  AV_Manager* av_manager;
  Vaccine_Manager* vacc_manager;

  /**
   * Write out the population in a format similar to the population input files (with additional runtime information)
   * @param day the simulation day
   */
  void write_population_output_file(int day);

  // functors for demographics updates 
  struct Update_Population_Births {
    int day;
    Update_Population_Births(int _day) : day(_day) { }
    void operator() (Person &p);
  };

  struct Update_Population_Deaths {
    int day;
    Update_Population_Deaths(int _day) : day(_day) { }
    void operator() (Person &p);
  };

  // functor for health interventions (vaccination & antivirals) updates
  struct Update_Health_Interventions {
    int day;
    Update_Health_Interventions(int d) : day(d) { }
    void operator() (Person &p );
  };
    
  // functor for health update
  struct Update_Population_Health {
    int day;
    Update_Population_Health(int d) : day(d) { }
    void operator() (Person &p);
  };

  // functor for prepare activities
  struct Prepare_Population_Activities {
    int day;
    Prepare_Population_Activities(int d) : day(d) { }
    void operator() (Person &p);
  };

  // functor for activity profile update
  struct Update_Population_Activities {
    int day;
    Update_Population_Activities(int d) : day(d) { }
    void operator() (Person &p);
  };

  struct update_activities {
    int day, disease_id;
    update_activities(int _day, int _disease_id) : day(_day), disease_id(_disease_id) { };
    void operator() (Person &p);
  };

  struct update_susceptible_activities {
    int day;
    update_susceptible_activities(int _day) : day(_day) { };
    void operator() (Person &p);
  };

  struct update_infectious_activities {
    int day;
    update_infectious_activities(int _day) : day(_day) { };
    void operator() (Person &p);
  };
  
  struct update_activities_while_traveling {
    int day;
    update_activities_while_traveling(int _day) : day(_day) { };
    void operator() (Person &p);
  };
  
  // functor for behavior setup
  struct Setup_Population_Behavior {
    void operator() (Person &p);
  };

  // functor for Health Insurance setup
  struct Setup_Population_Health_Insurance {
    void operator() (Person &p);
  };

  // functor for behavior updates
  struct Update_Population_Behaviors {
    int day;
    Update_Population_Behaviors(int d) : day(d) { }
    void operator() (Person &p);
  };

  struct infectious_sampler {
    double prob;
    vector<Person*>* samples;
    void operator() (Person &p);
  };

  fred::Mutex mutex;
  fred::Mutex add_person_mutex;
  fred::Mutex batch_add_person_mutex;

  void add_to_birthday_list(Person* person);
  void delete_from_birthday_list(Person* person);
  void update_people_on_birthday_list(int day);

};

struct Person_Init_Data {

  char house_label[32], school_label[32], work_label[32];
  char label[32];
  int age, race, relationship;
  char sex;
  bool today_is_birthday;
  int day;
  Place* house;
  Place* work;
  Place* school;
  bool in_grp_qrtrs;
  char gq_type;

  Person_Init_Data() {
    default_initialization();
  }

  Person_Init_Data(int _age, int _race, int _relationship,
		   char _sex, bool _today_is_birthday, int _day) {

    default_initialization();
    age = _age;
    race = _race;
    relationship = _relationship;
    sex = _sex;
    today_is_birthday = _today_is_birthday;
    day = _day;
  }

  void default_initialization() {
    this->house = NULL;
    this->work = NULL;
    this->school = NULL;
    strcpy(this->label, "-1");
    strcpy(this->house_label, "-1");
    strcpy(this->school_label, "-1");
    strcpy(this->work_label, "-1");
    this->age = -1;
    this->race = -1;
    this->relationship = -1;
    this->sex = -1;
    this->day = 0;
    this->today_is_birthday = false;
    this->in_grp_qrtrs = false;
    this->gq_type = ' ';
  }

  const std::string to_string() const {
    std::stringstream ss;
    //ss << setw( 8 ) << setfill( ' ' ); 
    ss << "Person Init Data:"
       << " label " << this->label
       << " age " << this->age
       << " race " << this->race
       << " relationship " << this->relationship
       << " today_is_birthday? " << this->today_is_birthday
       << " day " << this->day
       << " house_label " << this->house_label
       << " work_label " << this->work_label
       << " school_label " << this->school_label
       << " in_group_quarters? " << this->in_grp_qrtrs;

    return ss.str();
  }

};

#endif // _FRED_POPULATION_H
back to top