RandomInitialInfections.java
- package org.matsim.episim.model;
- import com.google.common.collect.Lists;
- import com.google.inject.Inject;
- import it.unimi.dsi.fastutil.objects.Object2IntAVLTreeMap;
- import it.unimi.dsi.fastutil.objects.Object2IntMap;
- import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
- import org.matsim.api.core.v01.Id;
- import org.matsim.api.core.v01.population.Person;
- import org.matsim.core.config.Config;
- import org.matsim.core.config.ConfigUtils;
- import org.matsim.episim.EpisimConfigGroup;
- import org.matsim.episim.EpisimPerson;
- import org.matsim.episim.EpisimUtils;
- import java.time.LocalDate;
- import java.util.List;
- import java.util.Map;
- import java.util.NavigableMap;
- import java.util.SplittableRandom;
- import java.util.stream.Collectors;
- /**
- * Randomly infect persons, optionally filtering by age group and district.
- */
- public class RandomInitialInfections implements InitialInfectionHandler {
- private static final Logger log = LogManager.getLogger(RandomInitialInfections.class);
- private final EpisimConfigGroup episimConfig;
- private final SplittableRandom rnd;
- private int initialInfectionsLeft;
- @Inject
- public RandomInitialInfections(Config config, SplittableRandom rnd) {
- this.episimConfig = ConfigUtils.addOrGetModule(config, EpisimConfigGroup.class);
- this.rnd = rnd;
- }
- @Override
- public Object2IntMap<VirusStrain> handleInfections(Map<Id<Person>, EpisimPerson> persons, int iteration) {
- if (initialInfectionsLeft == 0) return new Object2IntAVLTreeMap<>();
- double now = EpisimUtils.getCorrectedTime(episimConfig.getStartOffset(), 0, iteration);
- String district = episimConfig.getInitialInfectionDistrict();
- int lowerAgeBoundaryForInitInfections = episimConfig.getLowerAgeBoundaryForInitInfections();
- int upperAgeBoundaryForInitInfections = episimConfig.getUpperAgeBoundaryForInitInfections();
- LocalDate date = episimConfig.getStartDate().plusDays(iteration - 1);
- // int infected = 0;
- Object2IntMap<VirusStrain> infectedByStrain = new Object2IntAVLTreeMap<>();
- for (Map.Entry<VirusStrain, NavigableMap<LocalDate, Integer>> e : episimConfig.getInfections_pers_per_day().entrySet()) {
- infectedByStrain.put(e.getKey(), 0);
- int numInfections = EpisimUtils.findValidEntry(e.getValue(), 1, date);
- List<EpisimPerson> candidates = persons.values().stream()
- .filter(p -> district == null || district.equals(p.getAttributes().getAttribute("district")))
- .filter(p -> lowerAgeBoundaryForInitInfections == -1 || (int) p.getAttributes().getAttribute("microm:modeled:age") >= lowerAgeBoundaryForInitInfections)
- .filter(p -> upperAgeBoundaryForInitInfections == -1 || (int) p.getAttributes().getAttribute("microm:modeled:age") <= upperAgeBoundaryForInitInfections)
- .filter(p -> p.getDiseaseStatus() == EpisimPerson.DiseaseStatus.susceptible)
- .collect(Collectors.toList());
- if (candidates.size() < numInfections) {
- log.warn("Not enough persons match the initial infection requirement, using whole population...");
- candidates = Lists.newArrayList(persons.values());
- }
- while (numInfections > 0 && initialInfectionsLeft > 0 && candidates.size() > 0) {
- EpisimPerson randomPerson = candidates.remove(rnd.nextInt(candidates.size()));
- if (randomPerson.getDiseaseStatus() == EpisimPerson.DiseaseStatus.susceptible) {
- randomPerson.setInitialInfection(now, e.getKey());
- log.warn("Person {} has initial infection with {}.", randomPerson.getPersonId(), e.getKey());
- initialInfectionsLeft--;
- numInfections--;
- infectedByStrain.merge(e.getKey(), 1, Integer::sum);
- // infected++;
- }
- }
- }
- return infectedByStrain;
- }
- @Override
- public int getInfectionsLeft() {
- return initialInfectionsLeft;
- }
- @Override
- public void setInfectionsLeft(int num) {
- initialInfectionsLeft = num;
- }
- }