Program Listing for File Phage.h

Return to documentation for file (source/lysis_mode/Phage.h)

#ifndef PHAGE_H
#define PHAGE_H

#include "../default_mode/Symbiont.h"
#include "LysisWorld.h"

class Phage: public Symbiont {
protected:

  double burst_timer = 0;

  bool lysogeny = false;

  double incorporation_val = 0.0;

  double chance_of_lysis = 1;

  double induction_chance = 1;

  emp::Ptr<LysisWorld> my_world = NULL;


public:
  Phage(emp::Ptr<emp::Random> _random, emp::Ptr<LysisWorld> _world, emp::Ptr<SymConfigBase> _config, double _intval=0.0, double _points = 0.0) : Symbiont(_random, _world, _config, _intval, _points) {
    chance_of_lysis = my_config->LYSIS_CHANCE();
    induction_chance = my_config->CHANCE_OF_INDUCTION();
    incorporation_val = my_config->PHAGE_INC_VAL();
    if(chance_of_lysis == -1){
      chance_of_lysis = random->GetDouble(0.0, 1.0);
    }
    if(induction_chance == -1){
      induction_chance = random->GetDouble(0.0, 1.0);
    }
    if(incorporation_val == -1){
      incorporation_val = random->GetDouble(0.0, 1.0);
    }
    my_world = _world;
  }


  Phage(const Phage &) = default;


  Phage(Phage &&) = default;


  Phage() = default;

  std::string const GetName() {
    return  "Phage";
  }

  double GetBurstTimer() {return burst_timer;}


  void IncBurstTimer() {burst_timer += random->GetRandNormal(1.0, 1.0);}


  void SetBurstTimer(double _in) {burst_timer = _in;}


  double GetLysisChance() {return chance_of_lysis;}


  void SetLysisChance(double _in) {chance_of_lysis = _in;}

  double GetIncVal() {return incorporation_val;}


  void SetIncVal(double _in) {incorporation_val = _in;}

  double GetInductionChance() {return induction_chance;}

  void SetInductionChance(double _in) {induction_chance = _in;}

  bool GetLysogeny() {return lysogeny;}


  bool IsPhage() {return true;}


  void UponInjection() {
    double rand_chance = random->GetDouble(0.0, 1.0);
    if (rand_chance <= chance_of_lysis){
      lysogeny = false;
    } else {
      lysogeny = true;
    }
  }


  void Mutate() {
    Symbiont::Mutate();
    double local_rate = my_config->MUTATION_RATE();
    double local_size = my_config->MUTATION_SIZE();
    if (random->GetDouble(0.0, 1.0) <= local_rate) {
      //mutate chance of lysis/lysogeny, if enabled
      if(my_config->MUTATE_LYSIS_CHANCE()){
        chance_of_lysis += random->GetRandNormal(0.0, local_size);
        if(chance_of_lysis < 0) chance_of_lysis = 0;
        else if (chance_of_lysis > 1) chance_of_lysis = 1;
      }
      if(my_config->MUTATE_INDUCTION_CHANCE()){
        induction_chance += random->GetRandNormal(0.0, local_size);
        if(induction_chance < 0) induction_chance = 0;
        else if (induction_chance > 1) induction_chance = 1;
      }
      if(my_config->MUTATE_INC_VAL()){
        incorporation_val += random->GetRandNormal(0.0, local_size);
        if(incorporation_val < 0) incorporation_val = 0;
        else if (incorporation_val > 1) incorporation_val = 1;
      }
    }
  }

  emp::Ptr<Organism> MakeNew() {
    emp::Ptr<Phage> sym_baby = emp::NewPtr<Phage>(random, my_world, my_config, GetIntVal());
    // pass down parent's genome
    sym_baby->SetIncVal(GetIncVal());
    sym_baby->SetLysisChance(GetLysisChance());
    sym_baby->SetInductionChance(GetInductionChance());
    sym_baby->SetInfectionChance(GetInfectionChance());
    return sym_baby;
  }

  void LysisBurst(emp::WorldPosition location){
    emp::vector<emp::Ptr<Organism>>& repro_syms = my_host->GetReproSymbionts();
    //Record the burst size and count
    emp::DataMonitor<double>& data_node_burst_size = my_world->GetBurstSizeDataNode();
    data_node_burst_size.AddDatum(repro_syms.size());
    emp::DataMonitor<int>& data_node_burst_count = my_world->GetBurstCountDataNode();
    data_node_burst_count.AddDatum(1);
    emp::DataMonitor<int>& data_node_attempts_horiztrans = my_world->GetHorizontalTransmissionAttemptCount();
    emp::DataMonitor<int>& data_node_successes_horiztrans = my_world->GetHorizontalTransmissionSuccessCount();

    for(size_t r=0; r<repro_syms.size(); r++) {
      emp::WorldPosition new_pos = my_world->SymDoBirth(repro_syms[r], location);

      //horizontal transmission data nodes
      data_node_attempts_horiztrans.AddDatum(1);
      if(new_pos.IsValid()){
        data_node_successes_horiztrans.AddDatum(1);
      }
    }
    my_host->ClearReproSyms();
    my_host->SetDead();
    return;
  }

  void LysisStep(){
    IncBurstTimer();
    if(my_config->SYM_LYSIS_RES() == 0) {
      std::cout << "Lysis with a sym_lysis_res of 0 leads to an \
      infinite loop, please change" << std::endl;
      std::exit(1);
    }
    while(GetPoints() >= my_config->SYM_LYSIS_RES()) {
      emp::Ptr<Organism> sym_baby = Reproduce();
      my_host->AddReproSym(sym_baby);
      SetPoints(GetPoints() - my_config->SYM_LYSIS_RES());
    }
  }

  void VerticalTransmission(emp::Ptr<Organism> host_baby){
    //lysogenic phage have 100% chance of vertical transmission, lytic phage have 0% chance
    if(lysogeny){
      emp::Ptr<Organism> phage_baby = Reproduce();
      host_baby->AddSymbiont(phage_baby);

      //vertical transmission data node
      emp::DataMonitor<int>& data_node_attempts_verttrans = my_world->GetVerticalTransmissionAttemptCount();
      data_node_attempts_verttrans.AddDatum(1);
    }
  }


  double ProcessResources(double host_donation, emp::Ptr<Organism> host = nullptr){
    if(host == nullptr){
      host = my_host;
    }
    if(lysogeny){
      if(my_config->BENEFIT_TO_HOST()){
        return host->ProcessLysogenResources(incorporation_val);
      } else{
        return 0;
      }
    }
    else{
      return Symbiont::ProcessResources(host_donation, host); //lytic phage do steal resources
    }
  }

  void Process(emp::WorldPosition location) {
    if(my_config->LYSIS() && !GetHost().IsNull()) { //lysis enabled and phage is in a host
      if(!lysogeny){ //phage has chosen lysis
        if(GetBurstTimer() >= my_config->BURST_TIME() ) { //time to lyse!
          LysisBurst(location);
        }
        else { //not time to lyse
          LysisStep();
        }
      }
      else if(lysogeny){ //phage has chosen lysogeny
        double rand_chance = random->GetDouble(0.0, 1.0);
        if (rand_chance <= induction_chance){//phage has chosen to induce and turn lytic
          lysogeny = false;
        }
        else if(random->GetDouble(0.0, 1.0) <= my_config->PROPHAGE_LOSS_RATE()){ //check if the phage's host should become susceptible again
          SetDead();
        }
      }
    }

    else if (GetHost().IsNull() && my_config->FREE_LIVING_SYMS()) { //phage is free living
      my_world->MoveFreeSym(location);
    }
  }
};
#endif