Skip to content

Commit

Permalink
created new output analysis which find the home location for each inf…
Browse files Browse the repository at this point in the history
…ection. This is used to create infection location maps on covid-sim.
  • Loading branch information
jakobrehmann committed Aug 29, 2024
1 parent 499b793 commit f0a22e4
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/main/java/org/matsim/episim/EpisimReporting.java
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ void reporting(Map<String, InfectionReport> reports, int iteration, String date)

// Write all reports for each district
for (InfectionReport r : reports.values()) {
if (r.name.equals("total")) continue;
// if (r.name.equals("total")) continue;

String[] array = new String[InfectionsWriterFields.values().length];
array[InfectionsWriterFields.time.ordinal()] = Double.toString(r.time);
Expand Down
218 changes: 218 additions & 0 deletions src/main/java/org/matsim/episim/analysis/InfectionHomeLocation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
/* project: org.matsim.*
* *
* *********************************************************************** *
* *
* copyright : (C) 2020 by the members listed in the COPYING, *
* LICENSE and WARRANTY file. *
* email : info at matsim dot org *
* *
* *********************************************************************** *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* See also COPYING, LICENSE and WARRANTY file *
* *
* *********************************************************************** */

package org.matsim.episim.analysis;


import com.google.common.base.Joiner;
import com.google.inject.Inject;
import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
import it.unimi.dsi.fastutil.doubles.DoubleList;
import it.unimi.dsi.fastutil.ints.*;
import it.unimi.dsi.fastutil.objects.Object2DoubleMap;
import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.config.Configurator;
import org.matsim.api.core.v01.Coord;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.IdMap;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.population.Person;
import org.matsim.api.core.v01.population.Population;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.population.PopulationUtils;
import org.matsim.core.utils.geometry.CoordUtils;
import org.matsim.core.utils.geometry.CoordinateTransformation;
import org.matsim.core.utils.geometry.transformations.TransformationFactory;
import org.matsim.episim.*;
import org.matsim.episim.events.*;
import org.matsim.episim.model.VirusStrain;
import org.matsim.episim.model.progression.AgeDependentDiseaseStatusTransitionModel;
import org.matsim.run.AnalysisCommand;
import picocli.CommandLine;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;


/**
* @author smueller
* Calcualte vaccination effectiveness from events
*/
@CommandLine.Command(
name = "infHomeLoc",
description = "Finds the home location of infected persons."
)
public class InfectionHomeLocation implements OutputAnalysis {

@CommandLine.Option(names = "--output", defaultValue = "./output/")
private Path output;

@CommandLine.Option(names = "--input", defaultValue = "/scratch/projects/bzz0020/episim-input")
private String input;

@CommandLine.Option(names = "--population-file", defaultValue = "/cologne_snz_entirePopulation_emptyPlans_withDistricts_25pt_split.xml.gz")
private String populationFile;

@CommandLine.Option(names = "--input-crs", defaultValue = "EPSG:25832")

private String inputCRS;

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

private final String DAY = "daysSinceStart";

private final String HOME_LON = "home_lon";

private final String HOME_LAT = "home_lat";

@Inject
private Scenario scenario;

private Population population;
public static void main(String[] args) {
System.exit(new CommandLine(new InfectionHomeLocation()).execute(args));
}

@Override
public Integer call() throws Exception {
// logger configuration
Configurator.setLevel("org.matsim.core.config", Level.WARN);
Configurator.setLevel("org.matsim.core.controler", Level.WARN);
Configurator.setLevel("org.matsim.core.events", Level.WARN);
Configurator.setLevel("org.matsim.core.utils", Level.WARN);

// check if events file exists
if (!Files.exists(output)) {
log.error("Output path {} does not exist.", output);
return 2;
}

// read population
population = PopulationUtils.readPopulation(input + populationFile);


// Part 1: calculate home locs for each seed and save as csv
AnalysisCommand.forEachScenario(output, pathToScenario -> {
try {
// analyzeOutput is where the post processing
analyzeOutput(pathToScenario);

} catch (IOException e) {
log.error("Failed processing {}", pathToScenario, e);
}
});

log.info("done");


return 0;
}

@Override
public void analyzeOutput(Path pathToScenario) throws IOException {

if (scenario != null)
population = scenario.getPopulation();

String id = AnalysisCommand.getScenarioPrefix(pathToScenario);

// builds the path to the output file that is produced by this analysis
final Path csvPath = pathToScenario.resolve(id + "infectionLoc.csv");
CoordinateTransformation coordinateTransformation = TransformationFactory.getCoordinateTransformation(inputCRS, TransformationFactory.WGS84);;


// calculates home locations
try (BufferedWriter bw = Files.newBufferedWriter(csvPath)) {
Joiner joiner = Joiner.on(",");
bw.write(joiner.join(DAY, HOME_LON, HOME_LAT));
Handler handler = new Handler(population, coordinateTransformation);

List<String> eventFiles = AnalysisCommand.forEachEvent(pathToScenario, s -> {
}, true, handler);


if (handler.days.size() != handler.lons.size() || handler.days.size() != handler.lats.size()) {
throw new RuntimeException("all three datasets should have same size");
}

for (int i = 0; i < handler.days.size(); i++) {
bw.newLine();
bw.write(joiner.join(handler.days.getInt(i), handler.lons.get(i), handler.lats.get(i)));
}
}

log.info("Calculated results for output {}", pathToScenario);

}


public static final class Handler implements EpisimInfectionEventHandler, EpisimInitialInfectionEventHandler{
private final Population population;

private final IntList days;
private final List<Double> lats;
private final List<Double> lons;

private final CoordinateTransformation coordinateTransformation;


Handler(Population population, CoordinateTransformation coordinateTransformation) {

this.population = population;
this.coordinateTransformation = coordinateTransformation;
this.days = new IntArrayList();
this.lats = new ArrayList<>();
this.lons = new ArrayList<>();

}


@Override
public void handleEvent(EpisimInfectionEvent event) {

int day = (int) (event.getTime() / 86_400);
days.add(day);

double home_x = (double) population.getPersons().get(event.getPersonId()).getAttributes().getAttribute("homeX");
double home_y = (double) population.getPersons().get(event.getPersonId()).getAttributes().getAttribute("homeY");

Coord coord = new Coord(home_x, home_y);
Coord coordWgs84 = coordinateTransformation.transform(coord);

lats.add(Math.round(coordWgs84.getY() * 10000.0) / 10000.0);
lons.add(Math.round(coordWgs84.getX() * 10000.0) / 10000.0);

}

@Override
public void handleEvent(EpisimInitialInfectionEvent event) {
handleEvent(event.asInfectionEvent());
}


}
}
4 changes: 2 additions & 2 deletions src/main/java/org/matsim/run/CreateBatteryForCluster.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,10 @@ public class CreateBatteryForCluster<T> implements Callable<Integer> {
@CommandLine.Option(names = "--jvm-opts", description = "Additional options for JVM", defaultValue = "-Xms82G -Xmx82G -XX:+UseParallelGC")
private String jvmOpts;

@CommandLine.Option(names = "--setup", defaultValue = "org.matsim.run.batch.StarterBatchCologne")
@CommandLine.Option(names = "--setup", defaultValue = "org.matsim.run.batch.StarterBatchBrandenburg")
private Class<? extends BatchRun<T>> setup;

@CommandLine.Option(names = "--params", defaultValue = "org.matsim.run.batch.StarterBatchCologne$Params")
@CommandLine.Option(names = "--params", defaultValue = "org.matsim.run.batch.StarterBatchBrandenburg$Params")
private Class<T> params;

@SuppressWarnings("rawtypes")
Expand Down
12 changes: 7 additions & 5 deletions src/main/java/org/matsim/run/batch/StarterBatchBrandenburg.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.matsim.episim.BatchRun;
import org.matsim.episim.EpisimConfigGroup;
import org.matsim.episim.VirusStrainConfigGroup;
import org.matsim.episim.analysis.InfectionHomeLocation;
import org.matsim.episim.analysis.OutputAnalysis;
import org.matsim.episim.model.InfectionModelWithAntibodies;
import org.matsim.run.RunParallel;
Expand Down Expand Up @@ -41,7 +42,7 @@ private SnzBrandenburgProductionScenario getBindings(Params params) {
.setInfectionModel(InfectionModelWithAntibodies.class)
// .setEasterModel(SnzBerlinProductionScenario.EasterModel.no)
// .setChristmasModel(SnzBerlinProductionScenario.ChristmasModel.no)
.setSample(1)
.setSample(25)
.build();
}

Expand All @@ -59,7 +60,8 @@ public Metadata getMetadata() {
*/
@Override
public Collection<OutputAnalysis> postProcessing() {
return List.of();
return List.of(new InfectionHomeLocation().withArgs("--output","./output/","--input","/scratch/projects/bzz0020/episim-input",
"--population-file", "br_2020-week_snz_entirePopulation_emptyPlans_withDistricts_25pt_split.xml.gz"));
}

/*
Expand Down Expand Up @@ -91,10 +93,10 @@ public Config prepareConfig(int id, Params params) {
*/
public static final class Params {
// general
@GenerateSeeds(1)
@GenerateSeeds(5)
public long seed;

@Parameter({1.0, 2.0})
@Parameter({0.8, 0.9, 1.0, 1.1, 1.2})
public double thetaFactor;
}

Expand All @@ -108,7 +110,7 @@ public static void main(String[] args) {
RunParallel.OPTION_SETUP, StarterBatchBrandenburg.class.getName(),
RunParallel.OPTION_PARAMS, Params.class.getName(),
RunParallel.OPTION_TASKS, Integer.toString(8),
RunParallel.OPTION_ITERATIONS, Integer.toString(50),
RunParallel.OPTION_ITERATIONS, Integer.toString(20),
RunParallel.OPTION_METADATA
};

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/matsim/run/batch/UtilsJR.java
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ private static void producePlot(DateColumn records, DoubleColumn values, StringC
}


protected static void printInitialAntibodiesToConsole(Map<ImmunityEvent, Map<VirusStrain, Double>> initialAntibodies, boolean ignoreSuperfluous) {
public static void printInitialAntibodiesToConsole(Map<ImmunityEvent, Map<VirusStrain, Double>> initialAntibodies, boolean ignoreSuperfluous) {

List<ImmunityEvent> ignoredEvents = new ArrayList<>();
if (ignoreSuperfluous) {
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/collect.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ aggregate_run() {

rm -r "${tmp:?}/$run"

gzip --best *.infectionLoc.csv
copy_output *.infectionLoc.csv.gz $tmp

cd "$cwd" || exit
}

Expand Down

0 comments on commit f0a22e4

Please sign in to comment.