https://github.com/PublicHealthDynamicsLab/FRED
Revision a45e04ad99c865724a3c2b1a2d3fd979b3c6be88 authored by John Grefenstette on 07 January 2016, 16:32:02 UTC, committed by John Grefenstette on 07 January 2016, 16:32:02 UTC
1 parent 9bc2dce
Raw File
Tip revision: a45e04ad99c865724a3c2b1a2d3fd979b3c6be88 authored by John Grefenstette on 07 January 2016, 16:32:02 UTC
working markov epidemic model
Tip revision: a45e04a
Hospital.cc
/*
  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: Hospital.cc
//

#include <math.h>
#include <string>
#include <sstream>

#include "Disease.h"
#include "Disease_List.h"
#include "Global.h"
#include "Hospital.h"
#include "Params.h"
#include "Person.h"
#include "Place_List.h"
#include "Random.h"

class HAZEL_Hospital_Init_Data;

typedef std::map<std::string, HAZEL_Hospital_Init_Data> HospitalInitMapT;

//Private static variables that will be set by parameter lookups
double Hospital::contacts_per_day;
double** Hospital::prob_transmission_per_contact;
std::vector<double> Hospital::Hospital_health_insurance_prob;

bool Hospital::HAZEL_hospital_init_map_file_exists = false;
double Hospital::HAZEL_disaster_capacity_multiplier = 1.0;
int Hospital::HAZEL_mobile_van_open_delay = 0;
int Hospital::HAZEL_mobile_van_closure_day = 0;
std::vector<double> Hospital::HAZEL_reopening_CDF;
HospitalInitMapT Hospital::HAZEL_hospital_init_map;

Hospital::Hospital() : Place() {
  this->set_type(Place::TYPE_HOSPITAL);
  this->set_subtype(Place::SUBTYPE_NONE);
  this->bed_count = 0;
  this->occupied_bed_count = 0;
  this->daily_patient_capacity = -1;
  this->current_daily_patient_count = 0;
  this->add_capacity = false;

  if(Global::Enable_Health_Insurance) {
    vector<double>::iterator itr;
    int insr = static_cast<int>(Insurance_assignment_index::PRIVATE);
    for(itr = Hospital::Hospital_health_insurance_prob.begin(); itr != Hospital::Hospital_health_insurance_prob.end(); ++itr, ++insr) {
      set_accepts_insurance(insr, (Random::draw_random() < *itr));
    }
  }

  if(Global::Enable_HAZEL && Hospital::HAZEL_hospital_init_map_file_exists) {
    //Use the values read in from the map file
    if(Hospital::HAZEL_hospital_init_map.find(string(this->get_label())) != Hospital::HAZEL_hospital_init_map.end()) {
      HAZEL_Hospital_Init_Data init_data = Hospital::HAZEL_hospital_init_map.find(string(this->get_label()))->second;
      this->set_accepts_insurance(Insurance_assignment_index::HIGHMARK, init_data.accpt_highmark);
      this->set_accepts_insurance(Insurance_assignment_index::MEDICAID, init_data.accpt_medicaid);
      this->set_accepts_insurance(Insurance_assignment_index::MEDICARE, init_data.accpt_medicare);
      this->set_accepts_insurance(Insurance_assignment_index::PRIVATE, init_data.accpt_private);
      this->set_accepts_insurance(Insurance_assignment_index::UNINSURED, init_data.accpt_uninsured);
      this->set_accepts_insurance(Insurance_assignment_index::UPMC, init_data.accpt_upmc);
      if(init_data.is_mobile) {
        this->set_subtype(Place::SUBTYPE_MOBILE_HEALTHCARE_CLINIC);
      }
      this->set_daily_patient_capacity((init_data.panel_week / 5) + 1);
      this->add_capacity = init_data.add_capacity;
    }
  }
}

Hospital::Hospital(const char* lab, char _subtype, fred::geo lon, fred::geo lat) : Place(lab, lon, lat) {
  this->set_type(Place::TYPE_HOSPITAL);
  this->set_subtype(_subtype);
  this->bed_count = 0;
  this->occupied_bed_count = 0;
  this->daily_patient_capacity = -1;
  this->current_daily_patient_count = 0;
  this->add_capacity = false;

  if(Global::Enable_Health_Insurance) {
    vector<double>::iterator itr;
    int insr = static_cast<int>(Insurance_assignment_index::PRIVATE);
    for(itr = Hospital::Hospital_health_insurance_prob.begin(); itr != Hospital::Hospital_health_insurance_prob.end(); ++itr, ++insr) {
      set_accepts_insurance(insr, (Random::draw_random() < *itr));
    }
  }

  if(Global::Enable_HAZEL && Hospital::HAZEL_hospital_init_map_file_exists) {
    //Use the values read in from the map file
    if(Hospital::HAZEL_hospital_init_map.find(string(this->get_label())) != Hospital::HAZEL_hospital_init_map.end()) {
      HAZEL_Hospital_Init_Data init_data = Hospital::HAZEL_hospital_init_map.find(string(this->get_label()))->second;
      this->set_accepts_insurance(Insurance_assignment_index::HIGHMARK, init_data.accpt_highmark);
      this->set_accepts_insurance(Insurance_assignment_index::MEDICAID, init_data.accpt_medicaid);
      this->set_accepts_insurance(Insurance_assignment_index::MEDICARE, init_data.accpt_medicare);
      this->set_accepts_insurance(Insurance_assignment_index::PRIVATE, init_data.accpt_private);
      this->set_accepts_insurance(Insurance_assignment_index::UNINSURED, init_data.accpt_uninsured);
      this->set_accepts_insurance(Insurance_assignment_index::UPMC, init_data.accpt_upmc);
      if(init_data.is_mobile) {
        this->set_subtype(Place::SUBTYPE_MOBILE_HEALTHCARE_CLINIC);
      }
      this->set_daily_patient_capacity((init_data.panel_week / 5) + 1);
      this->add_capacity = init_data.add_capacity;
    }
  }
}

void Hospital::get_parameters() {
  Params::get_param_from_string("hospital_contacts", &Hospital::contacts_per_day);
  int n = Params::get_param_matrix((char *)"hospital_trans_per_contact", &Hospital::prob_transmission_per_contact);
  if(Global::Verbose > 1) {
    printf("\nHospital contact_prob:\n");
    for(int i  = 0; i < n; ++i)  {
      for(int j  = 0; j < n; ++j) {
	      printf("%f ", Hospital::prob_transmission_per_contact[i][j]);
      }
      printf("\n");
    }
  }

  if(Global::Enable_HAZEL) {
    char HAZEL_hosp_init_file_name[FRED_STRING_SIZE];
    char hosp_init_file_dir[FRED_STRING_SIZE];

    Params::get_param_vector((char*)"HAZEL_reopening_CDF", Hospital::HAZEL_reopening_CDF);
    Params::get_param_from_string("HAZEL_disaster_capacity_multiplier", &Hospital::HAZEL_disaster_capacity_multiplier);
    Params::get_param_from_string("HAZEL_mobile_van_open_delay", &Hospital::HAZEL_mobile_van_open_delay);
    Params::get_param_from_string("HAZEL_mobile_van_closure_day", &Hospital::HAZEL_mobile_van_closure_day);

    Params::get_param_from_string("HAZEL_hospital_init_file_directory", hosp_init_file_dir);
    Params::get_param_from_string("HAZEL_hospital_init_file_name", HAZEL_hosp_init_file_name);
    if(strcmp(HAZEL_hosp_init_file_name, "none") == 0) {
      Hospital::HAZEL_hospital_init_map_file_exists = false;
    } else {
      FILE* HAZEL_hosp_init_map_fp = NULL;

      char filename[FRED_STRING_SIZE];
      sprintf(filename, "%s%s", hosp_init_file_dir, HAZEL_hosp_init_file_name);
      HAZEL_hosp_init_map_fp = Utils::fred_open_file(filename);
      if(HAZEL_hosp_init_map_fp != NULL) {
        Hospital::HAZEL_hospital_init_map_file_exists = true;
        enum column_index {
          HOSP_ID = 0,
          PNL_WK = 1,
          ACCPT_PRIV = 2,
          ACCPT_MEDICR = 3,
          ACCPT_MEDICD = 4,
          ACCPT_HGHMRK = 5,
          ACCPT_UPMC = 6,
          ACCPT_UNINSRD = 7,
          REOPEN_AFTR_DAYS = 8,
          IS_MOBILE = 9,
          ADD_CAPACITY = 10
        };

        char line_str[255];
        int temp_int = 0;
        Utils::Tokens tokens;
        for(char* line = line_str; fgets(line, 255, HAZEL_hosp_init_map_fp); line = line_str) {
          tokens = Utils::split_by_delim(line, ',', tokens, false);
          // skip header line
          if(strcmp(tokens[HOSP_ID], "sp_id") != 0) {
            char place_type = Place::TYPE_HOSPITAL;
            char s[80];
            sprintf(s, "%c%s", place_type, tokens[HOSP_ID]);
            string hosp_id_str(s);
            HAZEL_Hospital_Init_Data init_data = HAZEL_Hospital_Init_Data(tokens[PNL_WK], tokens[ACCPT_PRIV],
              tokens[ACCPT_MEDICR], tokens[ACCPT_MEDICD], tokens[ACCPT_HGHMRK],
              tokens[ACCPT_UPMC], tokens[ACCPT_UNINSRD], tokens[REOPEN_AFTR_DAYS],
              tokens[IS_MOBILE], tokens[ADD_CAPACITY]);

	          Hospital::HAZEL_hospital_init_map.insert(std::pair<string, HAZEL_Hospital_Init_Data>(hosp_id_str, init_data));
          }
          tokens.clear();
        }
        fclose(HAZEL_hosp_init_map_fp);
      }
    }
  }

  if(Global::Enable_Health_Insurance || (Global::Enable_HAZEL && !Hospital::HAZEL_hospital_init_map_file_exists)) {
    Params::get_param_vector((char*)"hospital_health_insurance_prob", Hospital::Hospital_health_insurance_prob);
    assert(static_cast<int>(Hospital::Hospital_health_insurance_prob.size()) == static_cast<int>(Insurance_assignment_index::UNSET));
  }
}

int Hospital::get_group(int disease, Person* per) {
  // 0 - Healthcare worker
  // 1 - Patient
  // 2 - Visitor
  if(per->get_activities()->is_hospital_staff() && !per->is_hospitalized()) {
    return 0;
  }

  Place* hosp = per->get_activities()->get_hospital();
  if(hosp != NULL && hosp->get_id() == this->get_id()) {
    return 1;
  } else {
    return 2;
  }
}

double Hospital::get_transmission_prob(int disease, Person* i, Person* s) {
  // i = infected agent
  // s = susceptible agent
  int row = get_group(disease, i);
  int col = get_group(disease, s);
  double tr_pr = Hospital::prob_transmission_per_contact[row][col];
  return tr_pr;
}

int Hospital::get_bed_count(int sim_day) {
  if(Global::Enable_HAZEL) {
    if(sim_day < Place_List::get_HAZEL_disaster_end_sim_day()) {
      return this->bed_count;
    } else {
      if(this->add_capacity) {
        return static_cast<int>(ceil(Hospital::HAZEL_disaster_capacity_multiplier * this->bed_count));
      } else {
        return this->bed_count;
      }
    }
  } else {
    return this->bed_count;
  }
}

int Hospital::get_daily_patient_capacity(int sim_day) {
  if(Global::Enable_HAZEL) {
    if(sim_day < Place_List::get_HAZEL_disaster_end_sim_day()) {
      return this->daily_patient_capacity;
    } else {
      if(this->add_capacity) {
        return static_cast<int>(ceil(Hospital::HAZEL_disaster_capacity_multiplier * this->daily_patient_capacity));
      } else {
        return this->daily_patient_capacity;
      }
    }
  } else {
    return this->daily_patient_capacity;
  }
}

double Hospital::get_contacts_per_day(int disease) {
  return Hospital::contacts_per_day;
}

bool Hospital::is_open(int sim_day) {
  bool open = (sim_day < this->close_date || this->open_date <= sim_day);
  return open;
}

bool Hospital::should_be_open(int sim_day) {

  if(Global::Enable_HAZEL) {
    if(this->is_mobile_healthcare_clinic()) {
      if(sim_day <= (Place_List::get_HAZEL_disaster_end_sim_day() + Hospital::HAZEL_mobile_van_open_delay)) {
        //Not open until after disaster ends + some delay
        return false;
      } else {
        assert(this->HAZEL_closure_dates_have_been_set);
      }
    } else {
      // If we haven't made closure decision, do it now
      if(!this->HAZEL_closure_dates_have_been_set) {
        apply_individual_HAZEL_closure_policy();
      }
    }
  }
  return is_open(sim_day);
}

bool Hospital::should_be_open(int sim_day, int disease) {

  if(Global::Enable_HAZEL) {
    return this->should_be_open(sim_day);
  }

  return is_open(sim_day);
}

void Hospital::apply_individual_HAZEL_closure_policy() {
  assert(Global::Enable_HAZEL);
  if(!this->HAZEL_closure_dates_have_been_set) {
    if(Hospital::HAZEL_hospital_init_map_file_exists) {
      if(Hospital::HAZEL_hospital_init_map.find(string(this->get_label())) != Hospital::HAZEL_hospital_init_map.end()) {
        HAZEL_Hospital_Init_Data init_data = Hospital::HAZEL_hospital_init_map.find(string(this->get_label()))->second;
        if(init_data.reopen_after_days > 0) {
          if(Place_List::get_HAZEL_disaster_start_sim_day() != -1 && Place_List::get_HAZEL_disaster_end_sim_day() != -1) {
            this->set_close_date(Place_List::get_HAZEL_disaster_start_sim_day());
            this->set_open_date(Place_List::get_HAZEL_disaster_end_sim_day() + init_data.reopen_after_days);
            this->HAZEL_closure_dates_have_been_set = true;
            return;
          }
        } else if(init_data.reopen_after_days == 0 && !this->is_mobile_healthcare_clinic()) {
          if(Place_List::get_HAZEL_disaster_start_sim_day() != -1 && Place_List::get_HAZEL_disaster_end_sim_day() != -1) {
            this->set_open_date(0);
            this->HAZEL_closure_dates_have_been_set = true;
            return;
          }
        }
      }
    }
  } else {
    return;
  }

  if(!this->HAZEL_closure_dates_have_been_set) {
    int cdf_day = Random::draw_from_cdf_vector(Hospital::HAZEL_reopening_CDF);
    this->set_close_date(Place_List::get_HAZEL_disaster_start_sim_day());
    this->set_open_date(Place_List::get_HAZEL_disaster_end_sim_day() + cdf_day);
    this->HAZEL_closure_dates_have_been_set = true;
  }
}

void Hospital::set_accepts_insurance(Insurance_assignment_index::e insr, bool does_accept) {
  assert(insr >= Insurance_assignment_index::PRIVATE);
  assert(insr < Insurance_assignment_index::UNSET);
  switch(insr) {
    case Insurance_assignment_index::PRIVATE:
      this->accepted_insurance_bitset[Insurance_assignment_index::PRIVATE] = does_accept;
      break;
    case Insurance_assignment_index::MEDICARE:
      this->accepted_insurance_bitset[Insurance_assignment_index::MEDICARE] = does_accept;
      break;
    case Insurance_assignment_index::MEDICAID:
      this->accepted_insurance_bitset[Insurance_assignment_index::MEDICAID] = does_accept;
      break;
    case Insurance_assignment_index::HIGHMARK:
      this->accepted_insurance_bitset[Insurance_assignment_index::HIGHMARK] = does_accept;
      break;
    case Insurance_assignment_index::UPMC:
      this->accepted_insurance_bitset[Insurance_assignment_index::UPMC] = does_accept;
      break;
    case Insurance_assignment_index::UNINSURED:
      this->accepted_insurance_bitset[Insurance_assignment_index::UNINSURED] = does_accept;
      break;
    default:
      Utils::fred_abort("Invalid Insurance Assignment Type", "");
  }
}

void Hospital::set_accepts_insurance(int insr_indx, bool does_accept) {
  assert(insr_indx >= 0);
  assert(insr_indx < static_cast<int>(Insurance_assignment_index::UNSET));
  switch(insr_indx) {
    case static_cast<int>(Insurance_assignment_index::PRIVATE):
      set_accepts_insurance(Insurance_assignment_index::PRIVATE, does_accept);
      break;
    case static_cast<int>(Insurance_assignment_index::MEDICARE):
      set_accepts_insurance(Insurance_assignment_index::MEDICARE, does_accept);
      break;
    case static_cast<int>(Insurance_assignment_index::MEDICAID):
      set_accepts_insurance(Insurance_assignment_index::MEDICAID, does_accept);
      break;
    case static_cast<int>(Insurance_assignment_index::HIGHMARK):
      set_accepts_insurance(Insurance_assignment_index::HIGHMARK, does_accept);
      break;
    case static_cast<int>(Insurance_assignment_index::UPMC):
      set_accepts_insurance(Insurance_assignment_index::UPMC, does_accept);
      break;
    case static_cast<int>(Insurance_assignment_index::UNINSURED):
      set_accepts_insurance(Insurance_assignment_index::UNINSURED, does_accept);
      break;
    default:
      Utils::fred_abort("Invalid Insurance Assignment Type", "");
  }
}

std::string Hospital::to_string() {
  std::stringstream ss;
  ss << "Hospital[" << this->get_label() << "]: bed_count: " << this->bed_count
     << ", occupied_bed_count: " << this->occupied_bed_count
     << ", daily_patient_capacity: " << this->daily_patient_capacity
     << ", current_daily_patient_count: " << this->current_daily_patient_count
     << ", add_capacity: " << this->add_capacity
     << ", HAZEL_closure_dates_have_been_set: " << this->HAZEL_closure_dates_have_been_set
     << ", subtype: " << this->get_subtype();

  return ss.str();
}


back to top