EpisimConfigGroup.java
- /*-
- * #%L
- * MATSim Episim
- * %%
- * Copyright (C) 2020 matsim-org
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
- package org.matsim.episim;
- import com.google.common.annotations.Beta;
- import com.google.common.base.Joiner;
- import com.google.common.base.Splitter;
- import com.google.common.collect.Lists;
- import com.google.common.collect.Sets;
- import com.typesafe.config.Config;
- import com.typesafe.config.ConfigFactory;
- import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
- import org.magnos.trie.Trie;
- import org.magnos.trie.TrieMatch;
- import org.magnos.trie.Tries;
- import org.matsim.core.config.ConfigGroup;
- import org.matsim.core.config.ReflectiveConfigGroup;
- import org.matsim.episim.model.VirusStrain;
- import org.matsim.episim.policy.Restriction;
- import org.matsim.episim.policy.ShutdownPolicy;
- import javax.validation.constraints.NotNull;
- import java.io.File;
- import java.time.DayOfWeek;
- import java.time.LocalDate;
- import java.util.*;
- import java.util.stream.Collectors;
- /**
- * Main config for episim.
- */
- public final class EpisimConfigGroup extends ReflectiveConfigGroup {
- private static final Splitter.MapSplitter SPLITTER = Splitter.on(";").withKeyValueSeparator("=");
- private static final Joiner.MapJoiner JOINER = Joiner.on(";").withKeyValueSeparator("=");
- private static final String WRITE_EVENTS = "writeEvents";
- private static final String CALIBRATION_PARAMETER = "calibrationParameter";
- private static final String HOSPITAL_FACTOR = "hospitalFactor";
- private static final String INITIAL_INFECTIONS = "initialInfections";
- private static final String INITIAL_INFECTION_DISTRICT = "initialInfectionDistrict";
- private static final String INFECTIONS_PER_DAY = "infectionsPerDay";
- private static final String LOWER_AGE_BOUNDARY_FOR_INIT_INFECTIONS = "lowerAgeBoundaryForInitInfections";
- private static final String UPPER_AGE_BOUNDARY_FOR_INIT_INFECTIONS = "upperAgeBoundaryForInitInfections";
- private static final String MAX_CONTACTS = "maxContacts";
- private static final String SAMPLE_SIZE = "sampleSize";
- private static final String START_DATE = "startDate";
- private static final String SNAPSHOT_INTERVAL = "snapshotInterval";
- private static final String START_FROM_SNAPSHOT = "startFromSnapshot";
- private static final String START_FROM_IMMUNIZATION = "startFromImmunization";
- private static final String SNAPSHOT_PREFIX = "snapshotPrefix";
- private static final String SNAPSHOT_SEED = "snapshotSeed";
- private static final String LEISUREOUTDOORFRACTION = "leisureOutdoorFraction";
- private static final String INPUT_DAYS = "inputDays";
- private static final String DAYS_INFECTIOUS = "daysInfectious";
- private static final String ACTIVITY_HANDLING = "activityHandling";
- private static final String THREADS = "threads";
- private static final String CURFEW_COMPLIANCE = "curfewCompliance";
- private static final String DISTRICT_LEVEL_RESTRICTIONS = "districtLevelRestrictions";
- private static final String DISTRICT_LEVEL_RESTRICTIONS_ATTRIBUTE = "districtLevelRestrictionsAttribute";
- private static final String CONTAGIOUS_CONTAINER_OPTIMIZATION = "contagiousContainerOptimization";
- private static final String REPORT_TIME_USE = "reportTimeUse";
- private static final String SINGLE_EVENT_FILE = "singleEventFile";
- private static final String END_EARLY = "endEarly";
- private static final Logger log = LogManager.getLogger(EpisimConfigGroup.class);
- private static final String GROUPNAME = "episim";
- private final Trie<String, InfectionParams> paramsTrie = Tries.forStrings();
- /**
- * Number of initial infections per day.
- * Default is 1 infection per day for {@link VirusStrain#SARS_CoV_2}.
- */
- private final Map<VirusStrain, NavigableMap<LocalDate, Integer>> infectionsPerDay = new EnumMap<>(Map.of(VirusStrain.SARS_CoV_2, new TreeMap<>()));
- /**
- * Leisure outdoor fractions per day.
- */
- private final Map<LocalDate, Double> leisureOutdoorFraction = new TreeMap<>(Map.of(
- LocalDate.parse("2020-01-15"), 0.1,
- LocalDate.parse("2020-04-15"), 0.8,
- LocalDate.parse("2020-09-15"), 0.8,
- LocalDate.parse("2020-11-15"), 0.1,
- LocalDate.parse("2021-02-15"), 0.1,
- LocalDate.parse("2021-04-15"), 0.8,
- LocalDate.parse("2021-09-15"), 0.8)
- );
- /**
- * Re-mapping of specific dates to different week days events.
- */
- private final Map<LocalDate, DayOfWeek> inputDays = new HashMap<>();
- /**
- * Which events to write in the output.
- */
- private WriteEvents writeEvents = WriteEvents.episim;
- // this is current default for 25% scenarios
- private double calibrationParameter = 0.000002;
- private double hospitalFactor = 1.;
- private double sampleSize = 0.1;
- private int initialInfections = 10;
- private int lowerAgeBoundaryForInitInfections = -1;
- private int upperAgeBoundaryForInitInfections = -1;
- /**
- * If not null, filter persons for initial infection by district.
- */
- private String initialInfectionDistrict = null;
- /**
- * Start date of the simulation (Day 1).
- */
- private LocalDate startDate = LocalDate.of(1970, 1, 1);
- /**
- * Offset of start date in unix epoch seconds.
- */
- private long startOffset = 0;
- /**
- * Write snapshot every x days.
- */
- private int snapshotInterval = 0;
- /**
- * Path to snapshot file.
- */
- private String startFromSnapshot = null;
- private String startFromImmunization = null;
- /**
- * Filename prefix for snapshot.
- */
- private String snapshotPrefix = "episim-snapshot";
- /**
- * How the internal rng state should be handled.
- */
- private SnapshotSeed snapshotSeed = SnapshotSeed.restore;
- private FacilitiesHandling facilitiesHandling = FacilitiesHandling.snz;
- private ActivityHandling activityHandling = ActivityHandling.duringContact;
- private Config policyConfig = ConfigFactory.empty();
- private Config progressionConfig = ConfigFactory.empty();
- private String overwritePolicyLocation = null;
- private double maxContacts = 3.;
- private int daysInfectious = 4;
- private DistrictLevelRestrictions districtLevelRestrictions = DistrictLevelRestrictions.no;
- private String districtLevelRestrictionsAttribute = "";
- private ContagiousOptimization contagiousContainerOptimization = ContagiousOptimization.no;
- private ReportTimeUse reportTimeUse = ReportTimeUse.no;
- private SingleEventFile singleEventFile = SingleEventFile.yes;
- private boolean endEarly = false;
- private int threads = 2;
- /**
- * Compliance if a curfew is set.
- */
- private NavigableMap<LocalDate, Double> curfewCompliance = new TreeMap<>();
- /**
- * Default constructor.
- */
- public EpisimConfigGroup() {
- super(GROUPNAME);
- }
- public String getInputEventsFile() {
- List<EventFileParams> list = Lists.newArrayList(getInputEventsFiles());
- if (list.size() != 1) {
- throw new IllegalStateException("There is not exactly one input event file. Use .getEventFileParams() instead.");
- }
- return list.get(0).path;
- }
- /**
- * Adds one single input event file for all days of the week.
- */
- public void setInputEventsFile(String inputEventsFile) {
- clearParameterSetsForType(EventFileParams.SET_TYPE);
- addInputEventsFile(inputEventsFile)
- .addDays(DayOfWeek.values());
- }
- @StringSetter(THREADS)
- public void setThreads(int threads) {
- this.threads = threads;
- }
- @StringGetter(THREADS)
- public int getThreads() {
- return threads;
- }
- @StringGetter(WRITE_EVENTS)
- public WriteEvents getWriteEvents() {
- return writeEvents;
- }
- @StringSetter(WRITE_EVENTS)
- public void setWriteEvents(WriteEvents writeEvents) {
- this.writeEvents = writeEvents;
- }
- @StringGetter(CALIBRATION_PARAMETER)
- public double getCalibrationParameter() {
- return this.calibrationParameter;
- }
- @StringSetter(CALIBRATION_PARAMETER)
- public void setCalibrationParameter(double calibrationParameter) {
- this.calibrationParameter = calibrationParameter;
- }
- /**
- * Is multiplied with probability to transition to seriously sick in age dependent progression model
- */
- @StringGetter(HOSPITAL_FACTOR)
- public double getHospitalFactor() {
- return this.hospitalFactor;
- }
- @StringSetter(HOSPITAL_FACTOR)
- public void setHospitalFactor(double hospitalFactor) {
- this.hospitalFactor = hospitalFactor;
- }
- @StringGetter(INITIAL_INFECTIONS)
- public int getInitialInfections() {
- return this.initialInfections;
- }
- /**
- * @param initialInfections -- number of initial infections to start the dynamics. These will be distributed over several days.
- * @see #setInfections_pers_per_day(Map)
- */
- @StringSetter(INITIAL_INFECTIONS)
- public void setInitialInfections(int initialInfections) {
- this.initialInfections = initialInfections;
- }
- @StringGetter(LOWER_AGE_BOUNDARY_FOR_INIT_INFECTIONS)
- public int getLowerAgeBoundaryForInitInfections() {
- return this.lowerAgeBoundaryForInitInfections;
- }
- @StringSetter(LOWER_AGE_BOUNDARY_FOR_INIT_INFECTIONS)
- public void setLowerAgeBoundaryForInitInfections(int lowerAgeBoundaryForInitInfections) {
- this.lowerAgeBoundaryForInitInfections = lowerAgeBoundaryForInitInfections;
- }
- @StringGetter(UPPER_AGE_BOUNDARY_FOR_INIT_INFECTIONS)
- public int getUpperAgeBoundaryForInitInfections() {
- return this.upperAgeBoundaryForInitInfections;
- }
- @StringSetter(UPPER_AGE_BOUNDARY_FOR_INIT_INFECTIONS)
- public void setUpperAgeBoundaryForInitInfections(int upperAgeBoundaryForInitInfections) {
- this.upperAgeBoundaryForInitInfections = upperAgeBoundaryForInitInfections;
- }
- public Map<VirusStrain, NavigableMap<LocalDate, Integer>> getInfections_pers_per_day() {
- return infectionsPerDay;
- }
- /**
- * @param infectionsPerDay -- From each given date, this will be the number of infections. Until {@link #setInitialInfections(int)} are used up.
- */
- public void setInfections_pers_per_day(Map<LocalDate, Integer> infectionsPerDay) {
- this.setInfections_pers_per_day(VirusStrain.SARS_CoV_2, infectionsPerDay);
- }
- public void setInfections_pers_per_day(VirusStrain strain, Map<LocalDate, Integer> infectionsPerDay) {
- Map<LocalDate, Integer> perDay = this.infectionsPerDay.computeIfAbsent(strain, (k) -> new TreeMap<>());
- // yyyy Is it really so plausible to have this here _and_ the plain integer initial infections? kai, oct'20
- // yyyyyy Is it correct that the default of this is empty, so even if someone sets the initial infections to some number, this will not have any effect? kai, nov'20
- // No, If no entry is present, 1 will be assumed (because this was default at some point).
- // This logic of handling no entries is not part of the config, but the initial infection handler - cr, nov'20
- perDay.clear();
- perDay.putAll(infectionsPerDay);
- }
- @StringGetter(INFECTIONS_PER_DAY)
- String getInfectionsPerDay() {
- Map<VirusStrain, String> collect =
- infectionsPerDay.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> JOINER.join(e.getValue())));
- return Joiner.on("|").withKeyValueSeparator(">").join(collect);
- }
- @StringSetter(INFECTIONS_PER_DAY)
- void setInfectionsPerDay(String capacity) {
- Map<String, String> cap = Splitter.on("|").withKeyValueSeparator(">").split(capacity);
- for (Map.Entry<String, String> v : cap.entrySet()) {
- if (v.getValue().isBlank()) {
- setInfections_pers_per_day(VirusStrain.valueOf(v.getKey()), new TreeMap<>());
- continue;
- }
- Map<String, String> map = SPLITTER.split(v.getValue());
- setInfections_pers_per_day(VirusStrain.valueOf(v.getKey()), map.entrySet().stream().collect(Collectors.toMap(
- e -> LocalDate.parse(e.getKey()), e -> Integer.parseInt(e.getValue())
- )));
- }
- }
- @StringGetter(INITIAL_INFECTION_DISTRICT)
- public String getInitialInfectionDistrict() {
- return initialInfectionDistrict;
- }
- @StringSetter(INITIAL_INFECTION_DISTRICT)
- public void setInitialInfectionDistrict(String initialInfectionDistrict) {
- this.initialInfectionDistrict = initialInfectionDistrict;
- }
- @StringGetter(START_DATE)
- public LocalDate getStartDate() {
- return startDate;
- }
- @StringSetter(START_DATE)
- public void setStartDate(String startDate) {
- setStartDate(LocalDate.parse(startDate));
- }
- public void setStartDate(LocalDate startDate) {
- this.startDate = startDate;
- this.startOffset = EpisimUtils.getStartOffset(startDate);
- }
- @StringGetter(SNAPSHOT_INTERVAL)
- public int getSnapshotInterval() {
- return snapshotInterval;
- }
- @StringSetter(SNAPSHOT_INTERVAL)
- public void setSnapshotInterval(int snapshotInterval) {
- this.snapshotInterval = snapshotInterval;
- }
- @StringGetter(START_FROM_SNAPSHOT)
- public String getStartFromSnapshot() {
- return startFromSnapshot;
- }
- @StringSetter(START_FROM_SNAPSHOT)
- public void setStartFromSnapshot(String startFromSnapshot) {
- this.startFromSnapshot = startFromSnapshot;
- }
- @StringGetter(START_FROM_IMMUNIZATION)
- public String getStartFromImmunization() {
- return startFromImmunization;
- }
- @StringSetter(START_FROM_IMMUNIZATION)
- public void setStartFromImmunization(String startFromImmunization) {
- this.startFromImmunization = startFromImmunization;
- }
- @StringGetter(SNAPSHOT_PREFIX)
- public String getSnapshotPrefix() {
- return snapshotPrefix;
- }
- @StringSetter(SNAPSHOT_PREFIX)
- public void setSnapshotPrefix(String snapshotPrefix) {
- this.snapshotPrefix = snapshotPrefix;
- }
- @StringGetter(SNAPSHOT_SEED)
- public SnapshotSeed getSnapshotSeed() {
- return snapshotSeed;
- }
- @StringSetter(SNAPSHOT_SEED)
- public void setSnapshotSeed(SnapshotSeed snapshotSeed) {
- this.snapshotSeed = snapshotSeed;
- }
- public long getStartOffset() {
- return startOffset;
- }
- /**
- * Sample size in relation to whole population, between (0, 1].
- */
- @StringGetter(SAMPLE_SIZE)
- public double getSampleSize() {
- return sampleSize;
- }
- @StringSetter(SAMPLE_SIZE)
- public void setSampleSize(double sampleSize) {
- this.sampleSize = sampleSize;
- }
- @StringGetter("policyConfig")
- public String getPolicyConfig() {
- if (overwritePolicyLocation != null)
- return overwritePolicyLocation;
- return policyConfig.origin().filename();
- }
- /**
- * Set the policy config instance.
- */
- public void setPolicyConfig(Config policyConfig) {
- this.policyConfig = policyConfig;
- }
- /**
- * Sets policy config by loading it from a file first.
- *
- * @param policyConfig resource of filename to policy
- */
- @StringSetter("policyConfig")
- public void setPolicyConfig(String policyConfig) {
- if (policyConfig == null)
- this.policyConfig = ConfigFactory.empty();
- else {
- File file = new File(policyConfig);
- if (!policyConfig.equals("null") && !file.exists())
- throw new IllegalArgumentException("Policy config does not exist: " + policyConfig);
- this.policyConfig = ConfigFactory.parseFileAnySyntax(file);
- }
- }
- /**
- * Overwrite the policy location, which will be returned by {@link #getPolicyConfig()}.
- */
- public void setOverwritePolicyLocation(String overwritePolicyLocation) {
- this.overwritePolicyLocation = overwritePolicyLocation;
- }
- /**
- * Gets the actual policy configuration.
- */
- public Config getPolicy() {
- return policyConfig;
- }
- /**
- * Sets policy class and desired config.
- * @deprecated set policy class via guice.
- * @see #setPolicy(Config)
- */
- @Deprecated
- public void setPolicy(Class<? extends ShutdownPolicy> policy, Config config) {
- this.policyConfig = config;
- }
- /**
- * Sets policy config.
- */
- public void setPolicy(Config config) {
- this.policyConfig = config;
- }
- @StringGetter("progressionConfig")
- public String getProgressionConfigName() {
- if (progressionConfig.origin().filename() != null)
- return progressionConfig.origin().filename();
- return progressionConfig.origin().description();
- }
- /**
- * Gets the progression config configuration.
- */
- public Config getProgressionConfig() {
- return progressionConfig;
- }
- public void setProgressionConfig(Config progressionConfig) {
- this.progressionConfig = progressionConfig;
- }
- /**
- * Sets the progression config location as file name.
- */
- @StringSetter("progressionConfig")
- public void setProgressionConfig(String progressionConfig) {
- if (progressionConfig == null)
- this.progressionConfig = ConfigFactory.empty();
- else {
- File file = new File(progressionConfig);
- if (!progressionConfig.equals("null") && !file.exists())
- throw new IllegalArgumentException("Progression config does not exist: " + progressionConfig);
- this.progressionConfig = ConfigFactory.parseFileAnySyntax(file);
- }
- }
- @StringGetter(MAX_CONTACTS)
- public double getMaxContacts() {
- return maxContacts;
- }
- @StringSetter(MAX_CONTACTS)
- public void setMaxContacts(double maxContacts) {
- this.maxContacts = maxContacts;
- }
- @StringGetter(DAYS_INFECTIOUS)
- public int getDaysInfectious() {
- return daysInfectious;
- }
- @StringSetter(DAYS_INFECTIOUS)
- public void setDaysInfectious(int daysInfectious) {
- this.daysInfectious = daysInfectious;
- }
- /**
- * Sets the leisure outdoor fraction for the whole simulation period.
- */
- public void setLeisureOutdoorFraction(double fraction) {
- setLeisureOutdoorFraction(Map.of(LocalDate.of(1970, 1, 1), fraction));
- }
- /**
- * Sets the leisure outdoor fraction for individual days. If a day has no entry the values will be interpolated.
- */
- public void setLeisureOutdoorFraction(Map<LocalDate, Double> fraction) {
- leisureOutdoorFraction.clear();
- leisureOutdoorFraction.putAll(fraction);
- }
- public Map<LocalDate, Double> getLeisureOutdoorFraction() {
- return leisureOutdoorFraction;
- }
- @StringSetter(LEISUREOUTDOORFRACTION)
- void setLeisureOutdoorFraction(String capacity) {
- Map<String, String> map = SPLITTER.split(capacity);
- setLeisureOutdoorFraction(map.entrySet().stream().collect(Collectors.toMap(
- e -> LocalDate.parse(e.getKey()), e -> Double.parseDouble(e.getValue())
- )));
- }
- @StringGetter(LEISUREOUTDOORFRACTION)
- String getLeisureOutdoorFractionString() {
- return JOINER.join(leisureOutdoorFraction);
- }
- public NavigableMap<LocalDate, Double> getCurfewCompliance() {
- return curfewCompliance;
- }
- public void setCurfewCompliance(Map<LocalDate, Double> curfewCompliance) {
- this.curfewCompliance.clear();
- this.curfewCompliance.putAll(curfewCompliance);
- }
- @StringGetter(CURFEW_COMPLIANCE)
- String getCurfewComplianceString() {
- return JOINER.join(curfewCompliance);
- }
- @StringSetter(CURFEW_COMPLIANCE)
- void setCurfewCompliance(String config) {
- Map<String, String> map = SPLITTER.split(config);
- setCurfewCompliance(map.entrySet().stream().collect(Collectors.toMap(
- e -> LocalDate.parse(e.getKey()), e -> Double.parseDouble(e.getValue())
- )));
- }
- /**
- * Get remapping of input days.
- */
- public Map<LocalDate, DayOfWeek> getInputDays() {
- return inputDays;
- }
- public void setInputDays(Map<LocalDate, DayOfWeek> days) {
- this.inputDays.clear();
- this.inputDays.putAll(days);
- }
- @StringSetter(INPUT_DAYS)
- void setInputDays(String days) {
- Map<String, String> map = SPLITTER.split(days);
- setInputDays(map.entrySet().stream().collect(Collectors.toMap(
- e -> LocalDate.parse(e.getKey()), e -> DayOfWeek.valueOf(e.getValue())
- )));
- }
- @StringGetter(INPUT_DAYS)
- String getInputDaysString() {
- return JOINER.join(inputDays);
- }
- /**
- * Create restriction for each {@link InfectionParams}.
- */
- public Map<String, Restriction> createInitialRestrictions() {
- Map<String, Restriction> r = new LinkedHashMap<>();
- getContainerParams().forEach((s, p) -> r.put(s, Restriction.none()));
- return r;
- }
- @StringGetter("facilitiesHandling")
- public FacilitiesHandling getFacilitiesHandling() {
- return facilitiesHandling;
- }
- @StringSetter("facilitiesHandling")
- public void setFacilitiesHandling(FacilitiesHandling facilitiesHandling) {
- this.facilitiesHandling = facilitiesHandling;
- }
- @StringGetter(ACTIVITY_HANDLING)
- public ActivityHandling getActivityHandling() {
- return activityHandling;
- }
- @StringSetter(ACTIVITY_HANDLING)
- public void setActivityHandling(ActivityHandling activityHandling) {
- this.activityHandling = activityHandling;
- }
- /**
- * District level restrictions for location based restrictions;
- */
- @StringGetter(DISTRICT_LEVEL_RESTRICTIONS)
- public DistrictLevelRestrictions getDistrictLevelRestrictions() {
- return this.districtLevelRestrictions;
- }
- @StringSetter(DISTRICT_LEVEL_RESTRICTIONS)
- public void setDistrictLevelRestrictions(DistrictLevelRestrictions districtLevelRestrictions) {
- this.districtLevelRestrictions = districtLevelRestrictions;
- }
- @StringGetter(DISTRICT_LEVEL_RESTRICTIONS_ATTRIBUTE)
- public String getDistrictLevelRestrictionsAttribute() {
- return this.districtLevelRestrictionsAttribute;
- }
- @StringSetter(DISTRICT_LEVEL_RESTRICTIONS_ATTRIBUTE)
- public void setDistrictLevelRestrictionsAttribute(String districtLevelRestrictionsAttribute) {
- this.districtLevelRestrictionsAttribute = districtLevelRestrictionsAttribute;
- }
- @StringGetter(CONTAGIOUS_CONTAINER_OPTIMIZATION)
- public ContagiousOptimization getContagiousOptimization() {
- return this.contagiousContainerOptimization;
- }
- @StringSetter(CONTAGIOUS_CONTAINER_OPTIMIZATION)
- public void setContagiousOptimization(ContagiousOptimization contagiousOptimization) {
- this.contagiousContainerOptimization = contagiousOptimization;
- }
- @StringGetter(SINGLE_EVENT_FILE)
- public SingleEventFile getSingleEventFile() {
- return singleEventFile;
- }
- @StringSetter(SINGLE_EVENT_FILE)
- public void setSingleEventFile(SingleEventFile singleEventFile) {
- this.singleEventFile = singleEventFile;
- }
- @StringGetter(REPORT_TIME_USE)
- public ReportTimeUse getReportTimeUse() {
- return reportTimeUse;
- }
- @StringSetter(REPORT_TIME_USE)
- public void setReportTimeUse(ReportTimeUse reportTimeUse) {
- this.reportTimeUse = reportTimeUse;
- }
- @Override
- public void addParameterSet(final ConfigGroup set) {
- // this is, I think, necessary for the automatic reading from file, and possibly for the commandline stuff.
- switch (set.getName()) {
- case InfectionParams.SET_TYPE:
- addContainerParams((InfectionParams) set);
- break;
- case EventFileParams.SET_TYPE:
- super.addParameterSet(set);
- break;
- default:
- throw new IllegalArgumentException(set.getName());
- }
- }
- @Override
- public ConfigGroup createParameterSet(final String type) {
- switch (type) {
- case InfectionParams.SET_TYPE:
- return new InfectionParams();
- case EventFileParams.SET_TYPE:
- return new EventFileParams();
- default:
- throw new IllegalArgumentException(type);
- }
- }
- @Override
- protected void checkParameterSet(final ConfigGroup module) {
- switch (module.getName()) {
- case InfectionParams.SET_TYPE:
- if (!(module instanceof InfectionParams)) {
- throw new IllegalArgumentException("unexpected class for module " + module);
- }
- break;
- case EventFileParams.SET_TYPE:
- if (!(module instanceof EventFileParams)) {
- throw new IllegalArgumentException("unexpected class for module " + module);
- }
- break;
- default:
- throw new IllegalArgumentException(module.getName());
- }
- }
- /**
- * Adds given params to the parameter set, replacing existing ones.
- */
- public void addContainerParams(final InfectionParams params) {
- final InfectionParams previous = this.getContainerParams().get(params.getContainerName());
- Optional<String> match = params.mappedNames.stream().filter(s -> paramsTrie.get(s, TrieMatch.STARTS_WITH) != null).findAny();
- if (match.isPresent()) {
- throw new IllegalArgumentException("New param for " + match.get() + " matches one of the already present params. Try to define the params in different order.");
- }
- params.mappedNames.forEach(name -> paramsTrie.put(name, params));
- if (previous != null) {
- log.info("scoring parameters for activityType=" + previous.getContainerName() + " were just replaced.");
- params.mappedNames.forEach(paramsTrie::remove);
- final boolean removed = removeParameterSet(previous);
- if (!removed)
- throw new IllegalStateException("problem replacing params");
- }
- super.addParameterSet(params);
- }
- /**
- * Returns a container from the parameter set if it exists or creates a new one.
- */
- public InfectionParams getOrAddContainerParams(final String containerName, String... mappedNames) {
- InfectionParams params = this.getContainerParams().get(containerName);
- if (params != null)
- return params;
- params = new InfectionParams(containerName, mappedNames);
- addParameterSet(params);
- return params;
- }
- /**
- * Adds an event file to the config.
- */
- public EventFileParams addInputEventsFile(final String path) {
- for (EventFileParams f : getInputEventsFiles()) {
- if (f.path.equals(path)) throw new IllegalArgumentException("Input file already defined: " + path);
- }
- EventFileParams params = new EventFileParams(path);
- addParameterSet(params);
- return params;
- }
- /**
- * Removes all defined input files.
- */
- public void clearInputEventsFiles() {
- clearParameterSetsForType(EventFileParams.SET_TYPE);
- }
- /**
- * Get a copy of container params. Don't use this heavily, it is slow because a new map is created every time.
- */
- Map<String, InfectionParams> getContainerParams() {
- @SuppressWarnings("unchecked") final Collection<InfectionParams> parameters = (Collection<InfectionParams>) getParameterSets(InfectionParams.SET_TYPE);
- final Map<String, InfectionParams> map = new LinkedHashMap<>();
- for (InfectionParams pars : parameters) {
- if (this.isLocked()) {
- pars.setLocked();
- }
- map.put(pars.getContainerName(), pars);
- }
- return Collections.unmodifiableMap(map);
- }
- /**
- * Lookup which infection param is relevant for an activity. Throws exception when none was found.
- *
- * @param activity full activity identifier (including id etc.)
- * @return matched infection param
- * @throws NoSuchElementException when no param could be matched
- */
- @NotNull
- public InfectionParams selectInfectionParams(String activity) {
- InfectionParams params = paramsTrie.get(activity, TrieMatch.STARTS_WITH);
- if (params != null)
- return params;
- throw new NoSuchElementException(String.format("No params known for activity %s. Please add prefix to one infection parameter.", activity));
- }
- /**
- * Get the {@link InfectionParams} of a container by its name.
- */
- public InfectionParams getInfectionParam(String containerName) {
- return this.getContainerParams().get(containerName);
- }
- /**
- * All defined infection parameter.
- */
- public Collection<InfectionParams> getInfectionParams() {
- return (Collection<InfectionParams>) getParameterSets(InfectionParams.SET_TYPE);
- }
- /**
- * All defined input event files.
- */
- public Collection<EventFileParams> getInputEventsFiles() {
- return (Collection<EventFileParams>) getParameterSets(EventFileParams.SET_TYPE);
- }
- /**
- * Whether simulation ends when there are no further infected persons.
- */
- @StringGetter(END_EARLY)
- public boolean isEndEarly() {
- return endEarly;
- }
- @StringSetter(END_EARLY)
- public void setEndEarly(boolean endEarly) {
- this.endEarly = endEarly;
- }
- /**
- * Defines how facilities should be handled.
- */
- public enum FacilitiesHandling {
- /**
- * A facility id will be constructed using the link id where the activity is performed.
- */
- bln,
- /**
- * Facilities ids of activities will be used directly.
- */
- snz
- }
- /**
- * Defines which events will be written.
- */
- public enum WriteEvents {
- /**
- * Disable event writing completely.
- */
- none,
- /**
- * Write basic events like infections or disease status change.
- */
- episim,
- /**
- * Write the input event each day.
- */
- input,
- /**
- * Write additional contact tracing events.
- */
- tracing,
- /**
- * Write all, including input events.
- */
- all
- }
- /**
- * Defines how the snapshot seed should be processed.
- */
- public enum SnapshotSeed {
- /**
- * Restore rng state from the snapshot and continue as before.
- */
- restore,
- /**
- * Overwrite the rng state with a new seed taken from config.
- */
- reseed,
- }
- /**
- * Defines how activity participation is handled.
- */
- public enum ActivityHandling {
- /**
- * Activity participation is randdom during each contact.
- */
- duringContact,
- /**
- * Activity participation is fixed at start of the day.
- */
- startOfDay
- }
- /**
- * Decides whether location based restrictions should be implemented
- */
- public enum DistrictLevelRestrictions {
- yes,
- no
- }
- /**
- * In the case that this optimization is enabled, the infectionDynamics
- * methods are only called, if a contagious person is in the container
- */
- public enum ContagiousOptimization {
- yes,
- no
- }
- /**
- * The used time tracking costs a lot of CPU cycles, so this
- * can be disabled with
- */
- public enum ReportTimeUse {
- yes,
- no
- }
- /**
- * Whether to write all events into a single file.
- */
- public enum SingleEventFile {
- yes,
- no
- }
- /**
- * Parameter set for one activity type.
- */
- public static final class InfectionParams extends ReflectiveConfigGroup {
- public static final String ACTIVITY_TYPE = "activityType";
- public static final String CONTACT_INTENSITY = "contactIntensity";
- public static final String SPACES_PER_FACILITY = "nSpacesPerFacility";
- public static final String SEASONALITY = "seasonal";
- public static final String MAPPED_NAMES = "mappedNames";
- static final String SET_TYPE = "infectionParams";
- /**
- * Name of the container as reference by {@link ShutdownPolicy}.
- */
- private String containerName;
- /**
- * Prefixes of activity names that will be associated with this container type.
- */
- private Set<String> mappedNames;
- private double contactIntensity = 1.;
- /**
- * Typical number of distinct spaces per facility.
- */
- private double spacesPerFacility = 20.;
- /**
- * If 1.0, activity type is seasonal; 0.0 means it is not.
- */
- private double seasonality = 0.0;
- /**
- * See {@link #InfectionParams(String, String...)}. Name itself will also be used as prefix.
- */
- InfectionParams(final String containerName) {
- this();
- this.containerName = containerName;
- this.mappedNames = Sets.newHashSet(containerName);
- }
- /**
- * Constructor.
- *
- * @param containerName name of this activity type
- * @param mappedNames activity prefixes that will also be mapped to this container
- */
- InfectionParams(final String containerName, String... mappedNames) {
- this();
- this.containerName = containerName;
- this.mappedNames = mappedNames.length == 0 ?
- Sets.newHashSet(containerName) : Sets.newHashSet(mappedNames);
- }
- private InfectionParams() {
- super(SET_TYPE);
- }
- @StringGetter(MAPPED_NAMES)
- public String getMappedNames() {
- return Joiner.on(",").join(mappedNames);
- }
- @StringSetter(MAPPED_NAMES)
- void setMappedNames(String mappedNames) {
- this.mappedNames = Sets.newHashSet(mappedNames.split(","));
- }
- @StringGetter(ACTIVITY_TYPE)
- public String getContainerName() {
- return containerName;
- }
- @StringSetter(ACTIVITY_TYPE)
- void setContainerName(String actType) {
- this.containerName = actType;
- }
- /**
- * this is from iteration 0!
- */
- @StringGetter(CONTACT_INTENSITY)
- public double getContactIntensity() {
- return contactIntensity;
- }
- /**
- * this is from iteration 0!
- **/
- @StringSetter(CONTACT_INTENSITY)
- public InfectionParams setContactIntensity(double contactIntensity) {
- this.contactIntensity = contactIntensity;
- return this;
- }
- /**
- * Returns the spaces for facilities.
- *
- * @implNote Don't use this yet, may be removed or renamed.
- */
- @Beta
- @StringGetter(SPACES_PER_FACILITY)
- public double getSpacesPerFacility() {
- return spacesPerFacility;
- }
- @Beta
- @StringSetter(SPACES_PER_FACILITY)
- public InfectionParams setSpacesPerFacility(double nSpacesPerFacility) {
- this.spacesPerFacility = nSpacesPerFacility;
- return this;
- }
- @StringSetter(SEASONALITY)
- public InfectionParams setSeasonality(double seasonality) {
- this.seasonality = seasonality;
- return this;
- }
- /**
- * The extent of an activity's seasonal effects
- */
- @StringGetter(SEASONALITY)
- public double getSeasonality() {
- return seasonality;
- }
- /**
- * Check whether an activity belong to this container group.
- */
- public boolean includesActivity(String actType) {
- for (String mapped : mappedNames)
- if (actType.startsWith(mapped))
- return true;
- return false;
- }
- }
- /**
- * Event file configuration for certain weekdays.
- */
- public static final class EventFileParams extends ReflectiveConfigGroup {
- public static final String DAYS = "days";
- public static final String PATH = "path";
- static final String SET_TYPE = "eventFiles";
- private final Set<DayOfWeek> days = EnumSet.noneOf(DayOfWeek.class);
- private String path;
- EventFileParams(String path) {
- this();
- this.path = path;
- }
- private EventFileParams() {
- super(SET_TYPE);
- }
- @StringGetter(PATH)
- public String getPath() {
- return path;
- }
- @StringSetter(PATH)
- void setPath(String path) {
- this.path = path;
- }
- /**
- * Adds week days when this event file should be used.
- */
- public void addDays(DayOfWeek... days) {
- this.days.addAll(Arrays.asList(days));
- }
- @StringGetter(DAYS)
- public Set<DayOfWeek> getDays() {
- return days;
- }
- @StringSetter(DAYS)
- public void setDays(String days) {
- String str = days.replace("[", "").replace(" ", "").replace("]", "");
- this.days.addAll(
- Arrays.stream(str.split(",")).map(DayOfWeek::valueOf).collect(Collectors.toSet())
- );
- }
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- EventFileParams that = (EventFileParams) o;
- return path.equals(that.path) &&
- days.equals(that.days);
- }
- @Override
- public int hashCode() {
- return Objects.hash(path, days);
- }
- }
- }