Skip to content

Commit

Permalink
added analysis scripts from matsim-episim-libs
Browse files Browse the repository at this point in the history
  • Loading branch information
jakobrehmann committed Jan 28, 2025
1 parent 8b29c10 commit cfcc116
Show file tree
Hide file tree
Showing 30 changed files with 7,412 additions and 1 deletion.
1,035 changes: 1,035 additions & 0 deletions input/openDataModel/cologne/input/cologne_until20221231_mobility_data.csv

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
</licenses>

<properties>
<!-- <matsim.episim.version>2025.1</matsim.episim.version>-->
<matsim.episim.version>2025.1</matsim.episim.version>
<!--<matsim.version>12.0-2020w09-SNAPSHOT</matsim.version>-->
<mainClass>org.matsim.run.RunEpisim</mainClass>
Expand Down Expand Up @@ -87,7 +88,6 @@
</repositories>

<dependencies>

<dependency>
<groupId>com.github.matsim-org</groupId>
<artifactId>matsim-episim-libs</artifactId>
Expand Down
52 changes: 52 additions & 0 deletions src/main/java/org/matsim/episim/analysis/AnalyzeContactGraph.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package org.matsim.episim.analysis;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.DefaultUndirectedWeightedGraph;
import org.jgrapht.nio.graphml.GraphMLImporter;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.population.Person;
import org.matsim.core.utils.io.IOUtils;
import picocli.CommandLine;

import java.nio.file.Path;
import java.util.concurrent.Callable;

/**
* Executable class to analyze contacts events.
*/
@CommandLine.Command(
name = "analyzeGraph",
description = "Build contact graph from event file."
)
class AnalyzeContactGraph implements Callable<Integer> {

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

@CommandLine.Parameters(arity = "1")
private Path input;

public static void main(String[] args) {
System.exit(new CommandLine(new AnalyzeContactGraph()).execute(args));
}

@Override
public Integer call() throws Exception {

DefaultUndirectedWeightedGraph<Id<Person>, DefaultEdge> graph = new DefaultUndirectedWeightedGraph<>(DefaultEdge.class);

GraphMLImporter<Id<Person>, DefaultEdge> importer = new GraphMLImporter<>();
importer.setVertexFactory(Id::createPersonId);

importer.importGraph(graph, IOUtils.getBufferedReader(input.toString()));

log.info("Imported graph with {} edges and {} nodes", graph.edgeSet().size(), graph.vertexSet().size());


return 0;
}



}
191 changes: 191 additions & 0 deletions src/main/java/org/matsim/episim/analysis/AnalyzeDiviData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/* *********************************************************************** *
* project: org.matsim.*
* Controler.java
* *
* *********************************************************************** *
* *
* copyright : (C) 2007 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 java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Callable;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.core.utils.io.IOUtils;

import com.google.common.base.Joiner;
import it.unimi.dsi.fastutil.objects.Object2DoubleLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2DoubleMap;
import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import picocli.CommandLine;

/**
* @author: rewert
* This class reads the DIVI data for every day. The data is filtered for every Bundesland.
*/
@CommandLine.Command(name = "analyzeDIVIData", description = "Analyze DIVI data.")
public class AnalyzeDiviData implements Callable<Integer> {

private static final Logger log = LogManager.getLogger(AnalyzeDiviData.class);
private static final Joiner JOIN = Joiner.on("\t");

@CommandLine.Parameters(defaultValue = "../public-svn/matsim/scenarios/countries/de/episim/original-data/Fallzahlen/DIVI/Daily_reports/")
private Path inputFolder;

@CommandLine.Option(names = "--output", defaultValue = "../public-svn/matsim/scenarios/countries/de/episim/original-data/Fallzahlen/DIVI/")
private Path outputFolder;

public static void main(String[] args) {
System.exit(new CommandLine(new AnalyzeDiviData()).execute(args));
}

/**
* This method searches all files with an certain name in a given folder.
*/
private static List<File> findInputFiles(File inputFolder) {
List<File> fileData = new ArrayList<File>();

for (File file : Objects.requireNonNull(inputFolder.listFiles())) {
if (file.getName().contains("DIVI"))
fileData.add(file);
}
return fileData;
}

@Override
public Integer call() throws Exception {

HashMap<Integer, String> bundeslandCodes = new HashMap<Integer, String>();
bundeslandCodes.put(1, "Schleswig-Holstein");
bundeslandCodes.put(2, "Hamburg");
bundeslandCodes.put(3, "Niedersachsen");
bundeslandCodes.put(4, "Bremen");
bundeslandCodes.put(5, "Nordrhein-Westfalen");
bundeslandCodes.put(6, "Hessen");
bundeslandCodes.put(7, "Rheinland-Pfalz");
bundeslandCodes.put(8, "Baden-Wuertenberg");
bundeslandCodes.put(9, "Bayern");
bundeslandCodes.put(10, "Saarland");
bundeslandCodes.put(11, "Berlin");
bundeslandCodes.put(12, "Brandenburg");
bundeslandCodes.put(13, "Mecklenburg-Vorpommern");
bundeslandCodes.put(14, "Sachsen");
bundeslandCodes.put(15, "Sachsen-Anhalt");
bundeslandCodes.put(16, "Thueringen");

log.info("Searching for files in the folder: " + inputFolder);
List<File> filesWithData = findInputFiles(inputFolder.toFile());
log.info("Amount of found files: " + filesWithData.size());

analyzeDataForCertainArea("Bundesland", filesWithData, bundeslandCodes);

log.info("Done!");

return 0;
}

private void analyzeDataForCertainArea(String area, List<File> filesWithData, HashMap<Integer, String> bundeslandCodes) throws IOException {

log.info("Analyze data for " + area);

Path outputFile = outputFolder.resolve(area + "-divi-processed_until.csv");

BufferedWriter writer = IOUtils.getBufferedWriter(outputFile.toString());
try {

JOIN.appendTo(writer, HeaderTable.values());
writer.write("\n");

int countingDays = 1;

// will contain the last parsed date
String dateString = "";

for (File file : filesWithData) {

Object2IntMap<Integer> sums_casesCovidICU = new Object2IntLinkedOpenHashMap<>();
Object2IntMap<Integer> sums_beatmet = new Object2IntLinkedOpenHashMap<>();
Object2DoubleMap<Integer> sums_freeBeds = new Object2DoubleLinkedOpenHashMap<>();
Object2DoubleMap<Integer> sums_occupiedBeds = new Object2DoubleLinkedOpenHashMap<>();

dateString = file.getName().split("_")[1];

CSVParser parse = CSVFormat.DEFAULT.withDelimiter(',').withFirstRecordAsHeader()
.parse(IOUtils.getBufferedReader(file.toString()));

for (CSVRecord record : parse) {

int bundeslandCode = Integer.parseInt(record.get("bundesland"));
int aktuellICU = Integer.parseInt(record.get("faelle_covid_aktuell"));
int aktuellBeatmet = Integer.parseInt(record.get("faelle_covid_aktuell_beatmet"));
double freeBeds = Double.parseDouble(record.get("betten_frei"));
double occupiedBeds = Double.parseDouble(record.get("betten_belegt"));

sums_casesCovidICU.mergeInt(bundeslandCode, aktuellICU, Integer::sum);
sums_beatmet.mergeInt(bundeslandCode, aktuellBeatmet, Integer::sum);
sums_freeBeds.mergeDouble(bundeslandCode, freeBeds, Double::sum);
sums_occupiedBeds.mergeDouble(bundeslandCode, occupiedBeds, Double::sum);

}

for (int bundeslandCode : sums_beatmet.keySet()) {

List<String> row = new ArrayList<>();
row.add(dateString);

row.add(String.valueOf(bundeslandCodes.get(bundeslandCode)));
row.add(String.valueOf(sums_casesCovidICU.getInt(bundeslandCode)));
row.add(String.valueOf(sums_beatmet.getInt(bundeslandCode)));
row.add(String.valueOf(sums_freeBeds.getDouble(bundeslandCode)));
row.add(String.valueOf(sums_occupiedBeds.getDouble(bundeslandCode)));

JOIN.appendTo(writer, row);
writer.write("\n");
}

if (countingDays == 1 || countingDays % 5 == 0)
log.info("Finished day " + countingDays);

countingDays++;
}
writer.close();

Path finalPath = Path.of(outputFile.toString().replace("until", "until" + dateString));
Files.move(outputFile, finalPath, StandardCopyOption.REPLACE_EXISTING);

log.info("Write analyze of " + countingDays + " is writen to " + finalPath);
} catch (IOException e) {
e.printStackTrace();
}
}

private enum HeaderTable {
date, Bundesland, covid_faelle_aktuell, covid_aktuell_beatmet, bettenFrei, bettenBelegt
}
}
109 changes: 109 additions & 0 deletions src/main/java/org/matsim/episim/analysis/AnalyzeHomeFacilities.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/* *********************************************************************** *
* project: org.matsim.*
* Controler.java
* *
* *********************************************************************** *
* *
* copyright : (C) 2007 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 org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.population.Person;
import org.matsim.api.core.v01.population.Population;
import org.matsim.core.population.PopulationUtils;
import org.matsim.core.utils.geometry.CoordUtils;
import org.matsim.core.utils.io.IOUtils;
import org.matsim.facilities.*;

import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* This class aims to analyze the age distribution within home facilities of the input population. It classifies the inhabitants of each home facility into age groups and dumps
* out a csv containing the number of people belonging to every age group, for every home facility.
*/
final class AnalyzeHomeFacilities {

private static final String INPUT_POPULATION = "D:/svn/shared-svn/projects/episim/matsim-files/snz/Berlin/episim-input/be_entirePopulation_noPlans.xml.gz";
private static final String OUTPUT_CSV = "D:/svn/shared-svn/projects/episim/matsim-files/snz/Berlin/processed-data/be_entirePopulation_noPlans_homeIdCounts.csv";
private static final String OUTPUT_FACILITIES = "D:/svn/shared-svn/projects/episim/matsim-files/snz/Berlin/processed-data/be_entirePopulation_noPlans_homeFacilities.xml";

private AnalyzeHomeFacilities() {
}

public static void main(String[] args) {

Population population = PopulationUtils.readPopulation(INPUT_POPULATION);
Map<String, List<Person>> map = mapPersonsToHomeId(population);

BufferedWriter writer = IOUtils.getBufferedWriter(OUTPUT_CSV);

ActivityFacilities facilities = FacilitiesUtils.createActivityFacilities();
ActivityFacilitiesFactory factory = facilities.getFactory();

try {
writer.write("homeId;0-2;2-14;15-18;19-63;63-80;over80");
for (String home : map.keySet()) {
List<Person> inhabitants = map.get(home);

double x = (double) inhabitants.get(0).getAttributes().getAttribute("homeX");
double y = (double) inhabitants.get(0).getAttributes().getAttribute("homeY");

facilities.addActivityFacility(factory.createActivityFacility(Id.create(home, ActivityFacility.class), CoordUtils.createCoord(x,y)));

writer.newLine();
long nrClass1 = inhabitants.stream().map(person -> (int) person.getAttributes().getAttribute("age")).filter(age -> age <= 2).count();
long nrClass2 = inhabitants.stream().map(person -> (int) person.getAttributes().getAttribute("age")).filter(age -> age > 2 && age <= 14).count();
long nrClass3 = inhabitants.stream().map(person -> (int) person.getAttributes().getAttribute("age")).filter(age -> age > 14 && age <= 18).count();
long nrClass4 = inhabitants.stream().map(person -> (int) person.getAttributes().getAttribute("age")).filter(age -> age > 18 && age <= 63).count();
long nrClass5 = inhabitants.stream().map(person -> (int) person.getAttributes().getAttribute("age")).filter(age -> age > 63 && age <= 80).count();
long nrClass6 = inhabitants.stream().map(person -> (int) person.getAttributes().getAttribute("age")).filter(age -> age > 80).count();

writer.write(home + ";" + nrClass1 + ";" + nrClass2 + ";" + nrClass3 + ";" + nrClass4 + ";" + nrClass5 + ";" + nrClass6);
}
writer.close();

new FacilitiesWriter(facilities).write(OUTPUT_FACILITIES);
} catch (IOException e) {
e.printStackTrace();
}

}



private static Map<String, List<Person>> mapPersonsToHomeId(Population childrenPopulation) {
Map<String, List<Person>> homeIdToPersons = new HashMap<>();

for (Person person : childrenPopulation.getPersons().values()) {
String homeIdStr = person.getAttributes().getAttribute("homeId").toString();
if (homeIdToPersons.containsKey(homeIdStr)) {
homeIdToPersons.get(homeIdStr).add(person);
} else {
List<Person> list = new ArrayList<>();
list.add(person);
homeIdToPersons.put(homeIdStr, list);
}
}
return homeIdToPersons;
}


}
Loading

0 comments on commit cfcc116

Please sign in to comment.