From 6b20a9bbc325cb9bf1da9da279c4f198eb2522a8 Mon Sep 17 00:00:00 2001 From: simei94 <67737999+simei94@users.noreply.github.com> Date: Thu, 12 Oct 2023 17:51:35 +0200 Subject: [PATCH] blocked_road_use_case (#64) * make analysis trip based * saving of full trip not needed anymore because trip files will be loaded in R anyways * R analysis using matsim r functions based on java analysis * save file in RStudio before commit * finish up analysis * analysis on inetrzonal drt legs * replace logging statement using logger * reduce complexity * checkstyle --- .../drtAnalysis/DrtInterzonalTripsAnalysis.R | 66 ++++++++ .../blockedRoadAgentsAnalysis.R | 94 ++++++++++++ .../BlockedInfrastructureRouteAnalysis.java | 145 +++++++++--------- 3 files changed, 229 insertions(+), 76 deletions(-) create mode 100644 src/main/R/drtAnalysis/DrtInterzonalTripsAnalysis.R create mode 100644 src/main/R/populationAnalysis/blockedRoadAgentsAnalysis.R diff --git a/src/main/R/drtAnalysis/DrtInterzonalTripsAnalysis.R b/src/main/R/drtAnalysis/DrtInterzonalTripsAnalysis.R new file mode 100644 index 00000000..912b0fb6 --- /dev/null +++ b/src/main/R/drtAnalysis/DrtInterzonalTripsAnalysis.R @@ -0,0 +1,66 @@ +library(tidyverse) +library(matsim) +library(sf) + +# input shp files and the corresponding crs are defined here +CRS <- 25832 +zone1shpFile <- "../../shared-svn/projects/KelRide/data/ServiceAreas/2021-autumn-possibleAreasForAutomatedVehicles/Altstadt.shp" +zone2shpFile <- "../../shared-svn/projects/KelRide/data/ServiceAreas/2021-autumn-possibleAreasForAutomatedVehicles/Donaupark.shp" + +# input legs or trips file is defined here +it <- 999 +directory <- "Y:/net/ils/matsim-kelheim/run-roadBlock/output/kelheim-v2.0-network-with-pt.xml.gz-seed5678-CORE/" + +itDir <- paste0(directory,"ITERS/it.",it,"/") +legsOrTripsFile <- paste0(itDir,list.files(path = itDir, pattern = "*legs_av*")) + +zone1 <- st_read(zone1shpFile, crs=CRS) +zone2 <- st_read(zone2shpFile, crs=CRS) + +legsOrTripsTable <- read.csv2(legsOrTripsFile) %>% + rename(start_x = "fromX", + start_y = "fromY", + end_x = "toX", + end_y = "toY") + +# filter for legs / trips starting and ending in zones +departureInZone1 <- filterByRegion(legsOrTripsTable,zone1,crs=CRS,start.inshape = TRUE, end.inshape = FALSE) %>% + mutate(leg_id = paste0(personId,departureTime)) +arrivalInZone1 <- filterByRegion(legsOrTripsTable,zone1,crs=CRS,start.inshape = FALSE, end.inshape = TRUE) %>% + mutate(leg_id = paste0(personId,departureTime)) + +departureInZone2 <- filterByRegion(legsOrTripsTable,zone2,crs=CRS,start.inshape = TRUE, end.inshape = FALSE) %>% + mutate(leg_id = paste0(personId,departureTime)) +arrivalInZone2 <- filterByRegion(legsOrTripsTable,zone2,crs=CRS,start.inshape = FALSE, end.inshape = TRUE) %>% + mutate(leg_id = paste0(personId,departureTime)) + +#combine the above datasets to find legs / trips starting in one zone and ending in the other +zone1ToZone2 <- semi_join(departureInZone1, arrivalInZone2, by="leg_id") +zone2ToZone1 <- semi_join(departureInZone2, arrivalInZone1, by="leg_id") + +interzonalLegs <- union(zone1ToZone2,zone2ToZone1) + +meanTravTime <- mean(as.double(interzonalLegs$travelTime)) +meanTravDist <- mean(as.double(interzonalLegs$travelDistance_m)) +meanDirectTravDist <- mean(as.double(interzonalLegs$directTravelDistance_m)) +meanWaitTime <- mean(as.double(interzonalLegs$waitTime)) +interzonalLegsAbs <- nrow(interzonalLegs) +totalNoLegs <- nrow(legsOrTripsTable) +interzonalLegsRel <- interzonalLegsAbs / totalNoLegs + +#save avg values into df +avgValues <- setNames(data.frame(matrix(ncol = 6, nrow = 0)), c("meanTravTime[s]", "meanTravDist[m]", "meanDirectTravDist[m]", "meanWaitTime[s]","interzonalLegsAbsolute", "interzonalLegsRelative")) + +avgValuesDataset <- data.frame(meanTravTime, meanTravDist,meanDirectTravDist,meanWaitTime,interzonalLegsAbs,interzonalLegsRel) +names(avgValuesDataset) <- names(avgValues) +avgValues <- rbind(avgValues,avgValuesDataset) + +if(!file.exists(paste0(directory,"analysis-stop-2-stop"))) { + print("creating analysis sub-directory") + dir.create(paste0(directory,"analysis-stop-2-stop")) +} + +analysisDir <- paste0(directory,"/analysis-stop-2-stop/") + +write.table(interzonalLegs,paste0(analysisDir,"drt_legs_av_interzonal_AS_DP.csv"),quote=FALSE, row.names=FALSE, dec=".", sep=";") +write.table(avgValues,paste0(analysisDir,"avgValues_legs_interzonal_AS_DP.tsv"),quote=FALSE, row.names=FALSE, dec=".", sep="\t") \ No newline at end of file diff --git a/src/main/R/populationAnalysis/blockedRoadAgentsAnalysis.R b/src/main/R/populationAnalysis/blockedRoadAgentsAnalysis.R new file mode 100644 index 00000000..3e1466e7 --- /dev/null +++ b/src/main/R/populationAnalysis/blockedRoadAgentsAnalysis.R @@ -0,0 +1,94 @@ +library(tidyverse) +library(matsim) +library(ggalluvial) +library(lubridate) + + +setwd("Y:/net/ils/matsim-kelheim/run-roadBlock/output/") + +baseDir <- "Y:/net/ils/matsim-kelheim/run-roadBlock/output/kelheim-v2.0-network-with-pt.xml.gz-seed5678-CORE/" +policyDir <- "Y:/net/ils/matsim-kelheim/run-roadBlock/output/output-casekelheim-v2.0-network-with-pt_blocked-RegensburgerStr.xml.gz-seed5678-CORE/" + +tsvFile <- "analysis-road-usage/blocked_infrastructure_trip_comparison.tsv" + +ifelse(endsWith(policyDir, "/"),tsvFile <- tsvFile, tsvFile <- paste0("/",tsvFile)) + + +affectedTrips <- read.csv2(paste0(policyDir,tsvFile), stringsAsFactors = FALSE, header = TRUE, encoding = "UTF-8", sep="\t") + +tripsBase <- readTripsTable(pathToMATSimOutputDirectory = baseDir) +tripsPolicy <- readTripsTable(pathToMATSimOutputDirectory = policyDir) + +# filter trips with usage of blocked infrastructure in base case only +tripsBase <- tripsBase %>% + filter(trip_id %in% affectedTrips$trip_id) + +tripsPolicy <- tripsPolicy %>% + filter(trip_id %in% affectedTrips$trip_id) + +# join relevant trips by id and join + filter important stats only +tripsCombined <- left_join(tripsBase, tripsPolicy, by = "trip_id") %>% + filter(trip_number.x == trip_number.y) %>% + select(trip_id, + trav_time.x, + trav_time.y, + traveled_distance.x, + traveled_distance.y, + modes.x, + modes.y, + main_mode.x, + main_mode.y, + wait_time.x, + wait_time.y, + euclidean_distance.x, + euclidean_distance.y) %>% + rename("trav_time_base" = trav_time.x, + "trav_time_policy" = trav_time.y, + "traveled_distance_base" = traveled_distance.x, + "traveled_distance_policy" = traveled_distance.y, + "modes_base" = modes.x, + "modes_policy" = modes.y, + "main_mode_base" = main_mode.x, + "main_mode_policy" = main_mode.y, + "wait_time_base" = wait_time.x, + "wait_time_policy" = wait_time.y, + "euclidean_distance_base" = euclidean_distance.x, + "euclidean_distance_policy" = euclidean_distance.y) + +tripsCombined <- tripsCombined %>% + mutate(trav_time_diff_s = trav_time_policy - trav_time_base, + traveled_distance_diff_m = traveled_distance_policy - traveled_distance_base, + trav_time_base = seconds(trav_time_base), + trav_time_policy = seconds(trav_time_policy), + wait_time_base = seconds(wait_time_base), + wait_time_policy = seconds(wait_time_policy)) + +meanTravTimeBase <- mean(tripsCombined$trav_time_base) +meanTravTimePolicy <- mean(tripsCombined$trav_time_policy) +meanTravDistBase <- mean(tripsCombined$traveled_distance_base) +meanTravDistPolicy <- mean(tripsCombined$traveled_distance_policy) +meanEuclDistBase <- mean(tripsCombined$euclidean_distance_base) +meanEuclDistPolicy <- mean(tripsCombined$euclidean_distance_policy) +meanWaitTimeBase <- mean(tripsCombined$wait_time_base) +meanWaitTimePolicy <- mean(tripsCombined$wait_time_policy) + +tripsChangedMainMode <- tripsCombined %>% + filter(main_mode_base != main_mode_policy) + +noTripsChangedMainMode <- nrow(tripsChangedMainMode) + +#save avg values into df +avgValues <- setNames(data.frame(matrix(ncol = 9, nrow = 0)), c("meanTravTimeBase[s]", "meanTravTimePolicy[s]", "meanTravDistBase[m]", "meanTravDistPolicy[m]", "meanEuclDistBase[m]", + "meanEuclDistPolicy[m]", "meanWaitTimeBase[s]", "meanWaitTimePolicy[s]","nrTripsChangedMainMode")) + +avgValuesDataset <- data.frame(meanTravTimeBase, meanTravTimePolicy,meanTravDistBase,meanTravDistPolicy,meanEuclDistBase,meanEuclDistPolicy,meanWaitTimeBase,meanWaitTimePolicy,noTripsChangedMainMode) +names(avgValuesDataset) <- names(avgValues) +avgValues <- rbind(avgValues,avgValuesDataset) + +tsvFileName <- paste0("avg_params_blocked_infrastructure_agents.tsv") +write.table(avgValues,paste0(policyDir,"analysis-road-usage/",tsvFileName),quote=FALSE, row.names=FALSE, dec=".", sep="\t") +print(paste0("avg values for agents affected by blocked infrastructure ",policyDir,"analysis-road-usage/",tsvFileName)) + + + + diff --git a/src/main/java/org/matsim/analysis/postAnalysis/BlockedInfrastructureRouteAnalysis.java b/src/main/java/org/matsim/analysis/postAnalysis/BlockedInfrastructureRouteAnalysis.java index 99bf625c..b0d82998 100644 --- a/src/main/java/org/matsim/analysis/postAnalysis/BlockedInfrastructureRouteAnalysis.java +++ b/src/main/java/org/matsim/analysis/postAnalysis/BlockedInfrastructureRouteAnalysis.java @@ -2,6 +2,7 @@ import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; +import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.locationtech.jts.geom.Geometry; @@ -22,6 +23,7 @@ import picocli.CommandLine; import java.io.FileWriter; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; @@ -31,7 +33,7 @@ /** * Analyse routes for agents which use a certain infrastructure segment. * 1) Retrieves agents which use the infrastructure (e.g. in base case) - * 2) Searches for the (new) routes of the agents in a policy case + * 2) Save trips of those agents to tsv file for further R analysis. * * @author Simon Meinhardt (simei94) */ @@ -48,7 +50,7 @@ class BlockedInfrastructureRouteAnalysis implements MATSimAppCommand { @CommandLine.Mixin private ShpOptions shp = new ShpOptions(); - Map, Map> relevantLegsBase = new HashMap<>(); + Map, Map> relevantTripsBase = new HashMap<>(); public static void main(String[] args) { new BlockedInfrastructureRouteAnalysis().execute(args); @@ -63,7 +65,6 @@ public Integer call() throws Exception { Path basePopulationPath = globFile(directoryBase, "*output_plans*"); - Path policyPopulationPath = globFile(directoryBase, "*output_plans*"); //output will be written into policy case folder Path outputFolder = Path.of(directoryPolicy.toString() + "/analysis-road-usage"); @@ -78,63 +79,44 @@ public Integer call() throws Exception { Population populationBase = ScenarioUtils.loadScenario(config).getPopulation(); - config.plans().setInputFile(policyPopulationPath.toString()); - Population populationPolicy = ScenarioUtils.loadScenario(config).getPopulation(); - //get links, which are affected by blocked infrastructure List blockedLinks = getBlockedLinks(network, blockedInfrastructureArea); - relevantLegsBase = getLegsFromPlans(populationBase, blockedLinks); - Map, Map> relevantLegsPolicy = getLegsFromPlans(populationPolicy, blockedLinks); + relevantTripsBase = getTripsFromPlans(populationBase, blockedLinks); //writeResults - String outputFile = outputFolder + "/" + "blocked_infrastructure_leg_comparison.tsv"; + String outputFile = outputFolder + "/" + "blocked_infrastructure_trip_comparison.tsv"; CSVPrinter tsvPrinter = new CSVPrinter(new FileWriter(outputFile), CSVFormat.TDF); - List header = new ArrayList<>(); - header.add("person_id"); - header.add("tt_s_base"); - header.add("tt_s_policy"); - header.add("dist_m_base"); - header.add("dist_m_policy"); - header.add("mode_base"); - header.add("mode_policy"); - header.add("startLink_base"); - header.add("startLink_policy"); - header.add("endLink_base"); - header.add("endLink_policy"); - header.add("route_description_base"); - header.add("route_description_policy"); - - tsvPrinter.printRecord(header); - - for (Id personId : relevantLegsBase.keySet()) { - - for (Integer index : relevantLegsBase.get(personId).keySet()) { - - Map basePersonStats = relevantLegsBase.get(personId); - Map policyPersonStats = relevantLegsPolicy.get(personId); - - List entry = new ArrayList<>(); - entry.add(personId.toString()); - entry.add(String.valueOf(basePersonStats.get(index).getRoute().getTravelTime().seconds())); - entry.add(String.valueOf(policyPersonStats.get(index).getRoute().getTravelTime().seconds())); - entry.add(String.valueOf(basePersonStats.get(index).getRoute().getDistance())); - entry.add(String.valueOf(policyPersonStats.get(index).getRoute().getDistance())); - entry.add(basePersonStats.get(index).getMode()); - entry.add(policyPersonStats.get(index).getMode()); - entry.add(basePersonStats.get(index).getRoute().getStartLinkId().toString()); - entry.add(policyPersonStats.get(index).getRoute().getStartLinkId().toString()); - entry.add(basePersonStats.get(index).getRoute().getEndLinkId().toString()); - entry.add(policyPersonStats.get(index).getRoute().getEndLinkId().toString()); - entry.add(basePersonStats.get(index).getRoute().getRouteDescription()); - entry.add(policyPersonStats.get(index).getRoute().getRouteDescription()); - - tsvPrinter.printRecord(entry); + try { + List header = new ArrayList<>(); + header.add("person_id"); + header.add("trip_number"); + header.add("trip_id"); + + tsvPrinter.printRecord(header); + + for (Map.Entry, Map> entry : relevantTripsBase.entrySet()) { + + Integer tripNumber; + + for (Integer index : relevantTripsBase.get(entry.getKey()).keySet()) { + + tripNumber = index + 1; + + List outputEntry = new ArrayList<>(); + outputEntry.add(entry.getKey().toString()); + outputEntry.add(tripNumber.toString()); + outputEntry.add(entry.getKey() + "_" + tripNumber); + + tsvPrinter.printRecord(outputEntry); + } } + } catch (IOException e) { + log.log(Level.FATAL, e); + } finally { + tsvPrinter.close(); + log.log(Level.INFO, "Analysis output has been written to: {}", outputFile); } - tsvPrinter.close(); - - log.info("Analysis output has been written to: " + outputFile); return 0; } @@ -144,51 +126,62 @@ private List getBlockedLinks(Network network, Geometry geometry) { List blockedLinks = new ArrayList<>(); for (Link link : network.getLinks().values()) { - if (!link.getId().toString().contains("pt_")) { - if (isInsideArea(link, geometry)) { - blockedLinks.add(link.getId().toString()); - } + if (!link.getId().toString().contains("pt_") && isInsideArea(link, geometry)) { + blockedLinks.add(link.getId().toString()); } } return blockedLinks; } - private Map, Map> getLegsFromPlans(Population population, List blockedLinks) { + private Map, Map> getTripsFromPlans(Population population, List blockedLinks) { - Map, Map> relevantLegs = new HashMap<>(); + Map, Map> relevantTrips = new HashMap<>(); - if (relevantLegsBase.size() < 1) { + if (relevantTripsBase.size() < 1) { //base case log.info("Analyzing legs on blocked infrastructure for base case population"); for ( Person person : population.getPersons().values()) { //check if blocked link is part of leg-route - for ( Leg leg : TripStructureUtils.getLegs(person.getSelectedPlan())) { - for ( String linkId : blockedLinks ) { - if (leg.getRoute().getRouteDescription().contains(linkId)) { - relevantLegs.putIfAbsent(person.getId(), new HashMap<>()); - relevantLegs.get(person.getId()).put(person.getSelectedPlan().getPlanElements().indexOf(leg), leg); - continue; - } - } - } + + + + List trips = TripStructureUtils.getTrips(person.getSelectedPlan()); + + getTripsFromPersons(blockedLinks, person, trips, relevantTrips); } + } else { //policy case - //get corresponding legs to base case legs (where the now-blocked infrastructure is used) + //get corresponding trips to base case trips (where the now-blocked infrastructure is used) log.info("Analyzing legs on blocked infrastructure for policy case population"); - for (Id personId : relevantLegsBase.keySet()) { - for ( Integer index : relevantLegsBase.get(personId).keySet()) { - relevantLegs.putIfAbsent(personId, new HashMap<>()); - Leg policyLeg = (Leg) population.getPersons().get(personId).getSelectedPlan().getPlanElements().get(index); - relevantLegs.get(personId).put(population.getPersons().get(personId).getSelectedPlan().getPlanElements().indexOf(policyLeg), - policyLeg); + for (Map.Entry, Map> entry : relevantTripsBase.entrySet()) { + for ( Integer index : relevantTripsBase.get(entry.getKey()).keySet()) { + relevantTrips.putIfAbsent(entry.getKey(), new HashMap<>()); + + TripStructureUtils.Trip policyTrip = TripStructureUtils.getTrips(population.getPersons().get(entry.getKey()).getSelectedPlan()).get(index); + + relevantTrips.get(entry.getKey()).put(index, policyTrip); } } } - return relevantLegs; + return relevantTrips; + } + + private static void getTripsFromPersons(List blockedLinks, Person person, List trips, Map, Map> relevantTrips) { + for (int i = 0; i < trips.size(); i++) { + for (Leg leg : trips.get(i).getLegsOnly()) { + for ( String linkId : blockedLinks) { + if (leg.getRoute().getRouteDescription().contains(linkId)) { + relevantTrips.putIfAbsent(person.getId(), new HashMap<>()); + relevantTrips.get(person.getId()).put(i, trips.get(i)); + continue; + } + } + } + } } static boolean isInsideArea(Link link, Geometry geometry) {