示例#1
0
/**
 * Responds to an infection event by changing the herd's state from susceptible
 * to infected.
 *
 * @param self the model.
 * @param event an infection event.
 * @param rng a random number generator.
 */
void
handle_infection_event (struct naadsm_model_t_ *self,
                        EVT_infection_event_t * event, RAN_gen_t * rng)
{
  local_data_t *local_data;
  HRD_herd_t *herd;
  int latent_period, infectious_subclinical_period, infectious_clinical_period, immunity_period;
  unsigned int day_in_disease_cycle;

#if DEBUG
  g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "----- ENTER handle_infection_event (%s)", MODEL_NAME);
#endif

  local_data = (local_data_t *) (self->model_data);
  herd = event->infected_herd;
  if (local_data->production_type[herd->production_type] == FALSE)
    {
#if DEBUG
      g_debug ("unit is %s, sub-model does not apply", herd->production_type_name);
#endif
      goto end;
    }

  day_in_disease_cycle = 0;

  /* Latent period. */
  latent_period = (int) round (PDF_random (local_data->latent_period, rng));
  if (latent_period < 0)
    {
#if DEBUG
      g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
             "%s distribution returned %i for latent period, using 0 instead",
             PDF_dist_type_name[local_data->latent_period->type], latent_period);
#endif
      latent_period = 0;
    }
  if (event->override_initial_state == Latent)
    {
      if (event->override_days_in_state > 0 && event->override_days_left_in_state > 0)
        {
          /* Override both the days elapsed and the days left in the latent
           * period. */
          latent_period = event->override_days_in_state + event->override_days_left_in_state;
          day_in_disease_cycle = event->override_days_in_state;
        }
      else if (event->override_days_in_state > 0)
        {
          /* Override just the days elapsed in the latent period.  If the given
           * value is greater than the sampled length of the latent period,
           * extend the latent period. */
          latent_period = MAX(latent_period, event->override_days_in_state);
          day_in_disease_cycle = event->override_days_in_state;
        }
      else if (event->override_days_left_in_state > 0)
        {
          /* Override just the days left in the latent period.  If the given
           * value is greater than the sampled length of the latent period,
           * extend the latent period. */
          latent_period = MAX(latent_period, event->override_days_left_in_state);
          day_in_disease_cycle = latent_period - event->override_days_left_in_state;
        }
    }
#if DEBUG
  g_debug ("latent period will last %i days", latent_period);
#endif

  /* Infectious subclinical period. */
  infectious_subclinical_period =
    (int) round (PDF_random (local_data->infectious_subclinical_period, rng));
  if (infectious_subclinical_period < 0)
    {
#if DEBUG
      g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
             "%s distribution returned %i for infectious subclinical period, using 0 instead",
             PDF_dist_type_name[local_data->infectious_subclinical_period->type],
             infectious_subclinical_period);
#endif
      infectious_subclinical_period = 0;
    }
  if (event->override_initial_state == InfectiousSubclinical)
    {
      day_in_disease_cycle = latent_period;
      if (event->override_days_in_state > 0 && event->override_days_left_in_state > 0)
        {
          /* Override both the days elapsed and the days left in the infectious
           * subclinical period. */
          infectious_subclinical_period = event->override_days_in_state + event->override_days_left_in_state;
          day_in_disease_cycle += event->override_days_in_state;
        }
      else if (event->override_days_in_state > 0)
        {
          /* Override just the days elapsed in the infectious subclinical
           * period.  If the given value is greater than the sampled length of
           * the infectious subclinical period, extend the infectious
           * subclinical period. */
          infectious_subclinical_period = MAX(infectious_subclinical_period, event->override_days_in_state);
          day_in_disease_cycle += event->override_days_in_state;
        }
      else if (event->override_days_left_in_state > 0)
        {
          /* Override just the days left in the infectious subclinical period.
           * If the given value is greater than the sampled length of the
           * infectious subclinical period, extend the infectious subclinical
           * period. */
          infectious_subclinical_period = MAX(infectious_subclinical_period, event->override_days_left_in_state);
          day_in_disease_cycle += (infectious_subclinical_period - event->override_days_left_in_state);
        }
    }
#if DEBUG
  g_debug ("infectiousness (with no visible signs) will last %i days", infectious_subclinical_period);
#endif

  /* Infectious clinical period. */
  infectious_clinical_period =
    (int) round (PDF_random (local_data->infectious_clinical_period, rng));
  if (infectious_clinical_period < 0)
    {
#if DEBUG
      g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
             "%s distribution returned %i for infectious clinical period, using 0 instead",
             PDF_dist_type_name[local_data->infectious_clinical_period->type],
             infectious_clinical_period);
#endif
      infectious_clinical_period = 0;
    }
  if (event->override_initial_state == InfectiousClinical)
    {
      day_in_disease_cycle = latent_period + infectious_subclinical_period;
      if (event->override_days_in_state > 0 && event->override_days_left_in_state > 0)
        {
          /* Override both the days elapsed and the days left in the infectious
           * clinical period. */
          infectious_clinical_period = event->override_days_in_state + event->override_days_left_in_state;
          day_in_disease_cycle += event->override_days_in_state;
        }
      else if (event->override_days_in_state > 0)
        {
          /* Override just the days elapsed in the infectious clinical period.
           * If the given value is greater than the sampled length of the
           * infectious clinical period, extend the infectious clinical period. */
          infectious_clinical_period = MAX(infectious_clinical_period, event->override_days_in_state);
          day_in_disease_cycle += event->override_days_in_state;
        }
      else if (event->override_days_left_in_state > 0)
        {
          /* Override just the days left in the infectious clinical period.  If
           * the given value is greater than the sampled length of the
           * infectious clinical period, extend the infectious clinical period. */
          infectious_clinical_period = MAX(infectious_clinical_period, event->override_days_left_in_state);
          day_in_disease_cycle += (infectious_clinical_period - event->override_days_left_in_state);
        }
    }
#if DEBUG
  g_debug ("infectiousness (with visible signs) will last %i days", infectious_clinical_period);
#endif

  /* Natural immunity period. */
  immunity_period = (int) round (PDF_random (local_data->immunity_period, rng));
  if (immunity_period < 0)
    {
#if DEBUG
      g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
             "%s distribution returned %i for immunity period, using 0 instead",
             PDF_dist_type_name[local_data->immunity_period->type], immunity_period);
#endif
      immunity_period = 0;
    }
  if (event->override_initial_state == NaturallyImmune)
    {
      day_in_disease_cycle = latent_period + infectious_subclinical_period + infectious_clinical_period;
      if (event->override_days_in_state > 0 && event->override_days_left_in_state > 0)
        {
          /* Override both the days elapsed and the days left in the immunity
           * period. */
          immunity_period = event->override_days_in_state + event->override_days_left_in_state;
          day_in_disease_cycle += event->override_days_in_state;
        }
      else if (event->override_days_in_state > 0)
        {
          /* Override just the days elapsed in the immunity period.  If the
           * given value is greater than the sampled length of the immunity
           * period, extend the immunity period. */
          immunity_period = MAX(immunity_period, event->override_days_in_state);
          day_in_disease_cycle += event->override_days_in_state;
        }
      else if (event->override_days_left_in_state > 0)
        {
          /* Override just the days left in the immunity period.  If the given
           * value is greater than the sampled length of the immunity period,
           * extend the immunity period. */
          immunity_period = MAX(immunity_period, event->override_days_left_in_state);
          day_in_disease_cycle += (immunity_period - event->override_days_left_in_state);
        }
    }
#if DEBUG
  g_debug ("natural immunity will last %i days", immunity_period);
#endif

  HRD_infect (event->infected_herd, latent_period, infectious_subclinical_period,
              infectious_clinical_period, immunity_period, day_in_disease_cycle);

end:
#if DEBUG
  g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "----- EXIT handle_infection_event (%s)", MODEL_NAME);
#endif
  return;
}
示例#2
0
/**
 * Check whether herd 1 can infect herd 2 and if so, attempt to infect herd 2.
 * This function is used by both the naive search and the R-tree (spatial
 * index) search.
 */
void
check_and_infect (struct ergadm_model_t_ *self, HRD_herd_list_t * herds,
                  HRD_herd_t * herd1, HRD_herd_t * herd2,
                  EVT_new_day_event_t * event, RAN_gen_t * rng, EVT_event_queue_t * queue)
{
  local_data_t *local_data;
  gboolean herd2_can_be_target;
  param_block_t *param_block;
  double max_spread, distance, heading;
  double distance_factor, herd1_size_factor, herd2_size_factor;
  EVT_event_t *attempt_to_infect;
  double r, P;
  int delay;
  int delay_index;
  GQueue *q;
  HRD_expose_t exposure_update;
#if DEBUG
  GString *s;
#endif

#if DEBUG
  g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "----- ENTER check_and_infect (%s)", MODEL_NAME);
#endif

  /* Are herd 1 and herd 2 the same? */
  if (herd1 == herd2)
    goto end;

  local_data = (local_data_t *) (self->model_data);

  /* Can herd 2 be the target of an exposure? */
#if DEBUG
  s = g_string_new (NULL);
  g_string_sprintf (s, "unit \"%s\" is %s, state is %s: ",
                    herd2->official_id, herd2->production_type_name,
                    HRD_status_name[herd2->status]);
#endif
  param_block = local_data->param_block[herd1->production_type][herd2->production_type];
  herd2_can_be_target = (param_block != NULL && herd2->status != Destroyed);
#if DEBUG
  g_string_sprintfa (s, "%s be target", herd2_can_be_target ? "can" : "cannot");
  g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "%s", s->str);
  g_string_free (s, TRUE);
#endif
  if (!herd2_can_be_target)
    goto end;

  /* Is herd 2 close enough to herd 1? */
  distance = GIS_local_distance (herd1->lat, herd1->lon, herd2->lat, herd2->lon);
  max_spread = param_block->max_spread;
  if (distance - max_spread > EPSILON)
    {
#if DEBUG
      g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "  unit \"%s\" too far (%g > %g)",
             herd2->official_id, distance, max_spread);
#endif
      goto end;
    }
#if DEBUG
  g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "  unit \"%s\" within range (%g <= %g)",
         herd2->official_id, distance, max_spread);
#endif

  /* Is herd 2 within the wind direction range? */
  heading = GIS_local_heading (herd1->lat, herd1->lon, herd2->lat, herd2->lon);
  if (param_block->wind_range_crosses_0
      ? (param_block->wind_dir_start - heading > EPSILON
         && heading - param_block->wind_dir_end >=
         EPSILON) : (param_block->wind_dir_start - heading > EPSILON
                     || heading - param_block->wind_dir_end >= EPSILON))
    {
#if DEBUG
      g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
             "  unit \"%s\" outside wind angles (%g)", herd2->official_id, heading);
#endif
      goto end;
    }
#if DEBUG
  g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
         "  unit \"%s\" within wind angles (%g)", herd2->official_id, heading);
#endif

  distance_factor = (max_spread - distance) / (max_spread - 1);
  herd1_size_factor = local_data->herd_size_factor[herd1->index];
  herd2_size_factor = local_data->herd_size_factor[herd2->index];
#if DEBUG
  g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "  P = %g * %g * %g * %g * %g",
         herd1_size_factor, herd1->prevalence, distance_factor, param_block->prob_spread_1km,
         herd2_size_factor);
#endif

  P =
    herd1_size_factor * herd1->prevalence * distance_factor * param_block->prob_spread_1km *
    herd2_size_factor;
  r = RAN_num (rng);

  if (r < P && herd2->status == Susceptible)
    {
      if (NULL != guilib_record_exposure)
        {
          exposure_update.dest_index = herd2->index;
          exposure_update.dest_status = herd2->status;
          exposure_update.src_index = herd1->index;
          exposure_update.src_status = herd1->status;
          exposure_update.exposure_method = "A";
          exposure_update.success = -1;
          guilib_record_exposure (exposure_update);
        }

      attempt_to_infect =
        EVT_new_attempt_to_infect_event (herd1, herd2, event->day, "airborne spread");
      delay = (int) round (PDF_random (param_block->delay, rng));
      if (delay <= 0)
        {
          EVT_event_enqueue (queue, attempt_to_infect);
#if DEBUG
          g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "  r (%g) < P (%g), target herd infected", r, P);
#endif
        }
      else
        {
          attempt_to_infect->u.attempt_to_infect.day = event->day + delay;
          if (delay > local_data->pending_infections->len)
            ergadm_extend_rotating_array (local_data->pending_infections, delay,
                                          local_data->rotating_index);
          delay_index = (local_data->rotating_index + delay) % local_data->pending_infections->len;
          q = (GQueue *) g_ptr_array_index (local_data->pending_infections, delay_index);
          g_queue_push_tail (q, attempt_to_infect);
          local_data->npending_infections++;
#if DEBUG
          g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
                 "  r (%g) < P (%g), target unit will be infected on day %i",
                 r, P, event->day + delay);
#endif
        }
    }
  else
    {
      if (NULL != guilib_record_exposure)
        {
          exposure_update.dest_index = herd2->index;
          exposure_update.dest_status = herd2->status;
          exposure_update.src_index = herd1->index;
          exposure_update.src_status = herd1->status;
          exposure_update.exposure_method = "A";
          exposure_update.success = 0;
          guilib_record_exposure (exposure_update);
        }

#if DEBUG
      g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "  r (%g) >= P (%g), target unit not infected", r, P);
#endif
      ;
    }

end:
#if DEBUG
  g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "----- EXIT check_and_infect (%s)", MODEL_NAME);
#endif
  return;
}