RandomInitialInfections.java

  1. package org.matsim.episim.model;

  2. import com.google.common.collect.Lists;
  3. import com.google.inject.Inject;
  4. import it.unimi.dsi.fastutil.objects.Object2IntAVLTreeMap;
  5. import it.unimi.dsi.fastutil.objects.Object2IntMap;
  6. import org.apache.logging.log4j.LogManager;
  7. import org.apache.logging.log4j.Logger;
  8. import org.matsim.api.core.v01.Id;
  9. import org.matsim.api.core.v01.population.Person;
  10. import org.matsim.core.config.Config;
  11. import org.matsim.core.config.ConfigUtils;
  12. import org.matsim.episim.EpisimConfigGroup;
  13. import org.matsim.episim.EpisimPerson;
  14. import org.matsim.episim.EpisimUtils;

  15. import java.time.LocalDate;
  16. import java.util.List;
  17. import java.util.Map;
  18. import java.util.NavigableMap;
  19. import java.util.SplittableRandom;
  20. import java.util.stream.Collectors;

  21. /**
  22.  * Randomly infect persons, optionally filtering by age group and district.
  23.  */
  24. public class RandomInitialInfections implements InitialInfectionHandler {

  25.     private static final Logger log = LogManager.getLogger(RandomInitialInfections.class);

  26.     private final EpisimConfigGroup episimConfig;
  27.     private final SplittableRandom rnd;

  28.     private int initialInfectionsLeft;

  29.     @Inject
  30.     public RandomInitialInfections(Config config, SplittableRandom rnd) {
  31.         this.episimConfig = ConfigUtils.addOrGetModule(config, EpisimConfigGroup.class);
  32.         this.rnd = rnd;
  33.     }

  34.     @Override
  35.     public Object2IntMap<VirusStrain> handleInfections(Map<Id<Person>, EpisimPerson> persons, int iteration) {

  36.         if (initialInfectionsLeft == 0) return new Object2IntAVLTreeMap<>();

  37.         double now = EpisimUtils.getCorrectedTime(episimConfig.getStartOffset(), 0, iteration);

  38.         String district = episimConfig.getInitialInfectionDistrict();

  39.         int lowerAgeBoundaryForInitInfections = episimConfig.getLowerAgeBoundaryForInitInfections();
  40.         int upperAgeBoundaryForInitInfections = episimConfig.getUpperAgeBoundaryForInitInfections();

  41.         LocalDate date = episimConfig.getStartDate().plusDays(iteration - 1);

  42. //      int infected = 0;
  43.         Object2IntMap<VirusStrain> infectedByStrain = new Object2IntAVLTreeMap<>();

  44.         for (Map.Entry<VirusStrain, NavigableMap<LocalDate, Integer>> e : episimConfig.getInfections_pers_per_day().entrySet()) {

  45.             infectedByStrain.put(e.getKey(), 0);

  46.             int numInfections = EpisimUtils.findValidEntry(e.getValue(), 1, date);

  47.             List<EpisimPerson> candidates = persons.values().stream()
  48.                     .filter(p -> district == null || district.equals(p.getAttributes().getAttribute("district")))
  49.                     .filter(p -> lowerAgeBoundaryForInitInfections == -1 || (int) p.getAttributes().getAttribute("microm:modeled:age") >= lowerAgeBoundaryForInitInfections)
  50.                     .filter(p -> upperAgeBoundaryForInitInfections == -1 || (int) p.getAttributes().getAttribute("microm:modeled:age") <= upperAgeBoundaryForInitInfections)
  51.                     .filter(p -> p.getDiseaseStatus() == EpisimPerson.DiseaseStatus.susceptible)
  52.                     .collect(Collectors.toList());

  53.             if (candidates.size() < numInfections) {
  54.                 log.warn("Not enough persons match the initial infection requirement, using whole population...");
  55.                 candidates = Lists.newArrayList(persons.values());
  56.             }

  57.             while (numInfections > 0 && initialInfectionsLeft > 0 && candidates.size() > 0) {
  58.                 EpisimPerson randomPerson = candidates.remove(rnd.nextInt(candidates.size()));
  59.                 if (randomPerson.getDiseaseStatus() == EpisimPerson.DiseaseStatus.susceptible) {
  60.                     randomPerson.setInitialInfection(now, e.getKey());
  61.                     log.warn("Person {} has initial infection with {}.", randomPerson.getPersonId(), e.getKey());
  62.                     initialInfectionsLeft--;
  63.                     numInfections--;
  64.                     infectedByStrain.merge(e.getKey(), 1, Integer::sum);
  65. //                  infected++;

  66.                 }
  67.             }
  68.         }


  69.         return infectedByStrain;
  70.     }

  71.     @Override
  72.     public int getInfectionsLeft() {
  73.         return initialInfectionsLeft;
  74.     }

  75.     @Override
  76.     public void setInfectionsLeft(int num) {
  77.         initialInfectionsLeft = num;
  78.     }
  79. }