From 4ca906b64b20b8b40ecc66eb7f20d222daef20ba Mon Sep 17 00:00:00 2001 From: schlenther Date: Tue, 11 Jun 2024 15:20:05 +0200 Subject: [PATCH 1/9] update kexi config --- input/v3.1/kelheim-v3.1-25pct.kexi.config.xml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/input/v3.1/kelheim-v3.1-25pct.kexi.config.xml b/input/v3.1/kelheim-v3.1-25pct.kexi.config.xml index facb12ee..f4c927dc 100644 --- a/input/v3.1/kelheim-v3.1-25pct.kexi.config.xml +++ b/input/v3.1/kelheim-v3.1-25pct.kexi.config.xml @@ -265,11 +265,11 @@ - - - - - + + + + + - + + + + From 34f2283e18aa2b1938b093661bc8aac078a16bd2 Mon Sep 17 00:00:00 2001 From: simei94 Date: Thu, 13 Jun 2024 14:40:23 +0200 Subject: [PATCH 2/9] add test for mean nosie dashboard creation and analysis --- .../postAnalysis/NoiseAverageAnalysis.java | 21 ++- .../matsim/run/MeanNoiseDashboardTest.java | 133 ++++++++++++++++++ 2 files changed, 149 insertions(+), 5 deletions(-) create mode 100644 src/test/java/org/matsim/run/MeanNoiseDashboardTest.java diff --git a/src/main/java/org/matsim/analysis/postAnalysis/NoiseAverageAnalysis.java b/src/main/java/org/matsim/analysis/postAnalysis/NoiseAverageAnalysis.java index dc4593f0..33974c26 100644 --- a/src/main/java/org/matsim/analysis/postAnalysis/NoiseAverageAnalysis.java +++ b/src/main/java/org/matsim/analysis/postAnalysis/NoiseAverageAnalysis.java @@ -51,7 +51,6 @@ public class NoiseAverageAnalysis implements MATSimAppCommand { @CommandLine.Option(names = "--no-runs", defaultValue = "5", description = "Number of simulation runs to be averaged.") private Integer noRuns; - private final CsvOptions csv = new CsvOptions(); private static final String ANALYSIS_DIR = "/analysis/noise"; private static final String LINK_ID = "Link Id"; private static final String VALUE = "value"; @@ -65,6 +64,11 @@ public static void main(String[] args) { new NoiseAverageAnalysis().execute(args); } + public NoiseAverageAnalysis() { +// constructor needed for test only.. otherwise the read and write methods of this class would have to be copied, which is ugly. -sme0624 + + } + @Override public Integer call() throws Exception { String runs = input.getPath("runs"); @@ -76,13 +80,13 @@ public Integer call() throws Exception { final Path analysisDir = Path.of(folder + ANALYSIS_DIR); String emissionsCsv = globFile(analysisDir, "*emission_per_day.csv*").toString(); String imissionsPerDayAvro = globFile(analysisDir, "*immission_per_day.avro*").toString(); - String imissionsPerHourAvro = globFile(analysisDir, "*immission_per_day.avro*").toString(); + String imissionsPerHourAvro = globFile(analysisDir, "*immission_per_hour.avro*").toString(); // read Table emissions = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(emissionsCsv)) .columnTypesPartial(Map.of(LINK_ID, ColumnType.STRING, VALUE, ColumnType.DOUBLE)) .sample(false) - .separator(csv.detectDelimiter(emissionsCsv)).build()); + .separator(CsvOptions.detectDelimiter(emissionsCsv)).build()); // read avro file readAvroFile(imissionsPerDayAvro, imissionsPerDay); @@ -128,7 +132,10 @@ public Integer call() throws Exception { return 0; } - private void writeAvro(XYTData xytData, File outputFile) { + /** + * write an .avro file containing immission data. + */ + public void writeAvro(XYTData xytData, File outputFile) { DatumWriter datumWriter = new SpecificDatumWriter<>(XYTData.class); try (DataFileWriter dataFileWriter = new DataFileWriter<>(datumWriter)) { dataFileWriter.setCodec(CodecFactory.deflateCodec(9)); @@ -148,6 +155,7 @@ private XYTData calcAvroMeans(List recordList) { for (GenericRecord genericRecord: recordList) { +// for every record: 0 crs, 1 xCoords, 2 yCoords, 3 timeStamps, 4 actual immission data String object0 = genericRecord.get(0).toString(); Object object1 = genericRecord.get(1); Object object2 = genericRecord.get(2); @@ -225,7 +233,10 @@ private void getCoordData(Object object, List target) { } } - private void readAvroFile(String input, List target) { + /** + * read an .avro file containing immissions. + */ + public void readAvroFile(String input, List target) { try { // Read the schema from the Avro file FileReader fileReader = DataFileReader.openReader(new File(input), new GenericDatumReader<>()); diff --git a/src/test/java/org/matsim/run/MeanNoiseDashboardTest.java b/src/test/java/org/matsim/run/MeanNoiseDashboardTest.java new file mode 100644 index 00000000..e53ed822 --- /dev/null +++ b/src/test/java/org/matsim/run/MeanNoiseDashboardTest.java @@ -0,0 +1,133 @@ +package org.matsim.run; + +import org.apache.avro.generic.GenericData; +import org.apache.avro.generic.GenericRecord; +import org.apache.avro.util.Utf8; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.analysis.postAnalysis.NoiseAverageAnalysis; +import org.matsim.application.avro.XYTData; +import org.matsim.application.options.CsvOptions; +import org.matsim.application.prepare.network.CreateGeoJsonNetwork; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.dashboard.AverageKelheimNoiseDashboard; +import org.matsim.simwrapper.Dashboard; +import org.matsim.simwrapper.SimWrapper; +import org.matsim.testcases.MatsimTestUtils; +import tech.tablesaw.api.ColumnType; +import tech.tablesaw.api.Table; +import tech.tablesaw.io.csv.CsvReadOptions; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class MeanNoiseDashboardTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + + /** + * Test for building means over noise emission and immission values of several runs. The display of the values has to be done manually by looking at the resulting mean noise dashbaord. + */ + @Test + void runMeanNoiseDashboardTest() throws IOException { + + String networkPath = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/kelheim/kelheim-v3.0/input/kelheim-v3.0-network.xml.gz"; + String crs = "EPSG:25832"; + String path = utils.getInputDirectory(); + NoiseAverageAnalysis analysis = new NoiseAverageAnalysis(); + + List foldersSeeded = new ArrayList<>(); + + new CreateGeoJsonNetwork().execute(List.of("--network", networkPath, "--with-properties", "--shp", "./input/shp/dilutionArea.shp", "--output-network", path + "1seed/analysis/network/network.geojson", + "--input-crs", "EPSG:25832").toArray(new String[0])); + +// write dummy data + for (int i = 1; i <= 3; i++) { + List xCoords = new ArrayList<>(); + List yCoords = new ArrayList<>(); + List timeStamps = new ArrayList<>(); + Map> data = new HashMap<>(); + + xCoords.add(710419.08F); + xCoords.add(710424.82F); + yCoords.add(5421673.49F); + yCoords.add(5422288.95F); + + timeStamps.add(28800); + + data.put("imissions", List.of((float) i)); + + String seedDir = path + i + "seed/"; + foldersSeeded.add(seedDir); + +// write avro dummy files + Files.createDirectories(Path.of(seedDir + "analysis/noise/")); + analysis.writeAvro(new XYTData(crs, xCoords, yCoords, List.of(0), data), new File(seedDir + "analysis/noise/immission_per_day.avro")); + analysis.writeAvro(new XYTData(crs, xCoords, yCoords, timeStamps, data), new File(seedDir + "analysis/noise/immission_per_hour.avro")); + +// write emissions csv dummy file + try (CSVPrinter printer = new CSVPrinter(Files.newBufferedWriter(Path.of(seedDir + "analysis/noise/emission_per_day.csv")), CSVFormat.DEFAULT)) { + printer.printRecord("Link Id", "value"); + printer.printRecord("-27443742#0", i); + } + } + + SimWrapper sw = SimWrapper.create(); + sw.getConfigGroup().defaultParams().mapCenter = "11.89,48.91"; + sw.addDashboard(Dashboard.customize(new AverageKelheimNoiseDashboard(foldersSeeded, 3)).context("noise")); + try { + sw.generate(Path.of(path), true); + } catch (IOException e) { + throw new RuntimeException(e); + } + sw.run(Path.of(path)); + +// assert that: a) mean immission is 2.0 on daily and hourly data b) hourly data has timestamp 28800 c) mean emission is 2.0 + List daily = new ArrayList<>(); + List hourly = new ArrayList<>(); + analysis.readAvroFile(path + "analysis/postAnalysis-noise/mean_immission_per_day.avro", daily); + analysis.readAvroFile(path + "analysis/postAnalysis-noise/mean_immission_per_hour.avro", hourly); + + if (daily.getFirst().get(4) instanceof HashMap) { + Map.Entry entry = ((HashMap) daily.getFirst().get(4)).entrySet().stream().toList().getFirst(); + if (entry.getKey() instanceof Utf8 && entry.getValue() instanceof GenericData.Array) { + float dailyImmission = ((GenericData.Array) entry.getValue()).getFirst(); + Assertions.assertEquals(2.0, dailyImmission); + } + } + + if (hourly.getFirst().get(4) instanceof HashMap) { + Map.Entry entry = ((HashMap) hourly.getFirst().get(4)).entrySet().stream().toList().getFirst(); + if (entry.getKey() instanceof Utf8 && entry.getValue() instanceof GenericData.Array) { + float hourlyImmission = ((GenericData.Array) entry.getValue()).getFirst(); + Assertions.assertEquals(2.0, hourlyImmission); + } + } + + if (hourly.getFirst().get(3) instanceof GenericData.Array) { + int timeStamp = ((GenericData.Array) hourly.getFirst().get(3)).getFirst(); + Assertions.assertEquals(28800, timeStamp); + } + + Table emissions = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(path + "analysis/postAnalysis-noise/mean_emission_per_day.csv")) + .columnTypesPartial(Map.of("Link Id", ColumnType.STRING, "value", ColumnType.DOUBLE)) + .sample(false) + .separator(CsvOptions.detectDelimiter(path + "analysis/postAnalysis-noise/mean_emission_per_day.csv")).build()); + + String linkId = emissions.row(0).getString("Link Id"); + double emission = emissions.row(0).getDouble("value"); + + Assertions.assertEquals("-27443742#0", linkId); + Assertions.assertEquals(2.0, emission); + } +} From 7b95b054f791ab31c44f26e5b09fbbc9f35e7945 Mon Sep 17 00:00:00 2001 From: tschlenther Date: Wed, 19 Jun 2024 17:53:52 +0200 Subject: [PATCH 3/9] debug emission analysis: create injector and install EmissionModule --- ...elheimOfflineAirPollutionAnalysisByEngineInformation.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/matsim/analysis/emissions/KelheimOfflineAirPollutionAnalysisByEngineInformation.java b/src/main/java/org/matsim/analysis/emissions/KelheimOfflineAirPollutionAnalysisByEngineInformation.java index 099f658a..1d0c91c4 100644 --- a/src/main/java/org/matsim/analysis/emissions/KelheimOfflineAirPollutionAnalysisByEngineInformation.java +++ b/src/main/java/org/matsim/analysis/emissions/KelheimOfflineAirPollutionAnalysisByEngineInformation.java @@ -50,6 +50,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Injector; import org.matsim.core.events.EventsUtils; import org.matsim.core.events.MatsimEventsReader; import org.matsim.core.network.NetworkUtils; @@ -159,6 +160,10 @@ public void install(){ } }; + com.google.inject.Injector injector = Injector.createInjector(config, module); + // Emissions module will be installed to the event handler + injector.getInstance(EmissionModule.class); + EmissionsOnLinkEventHandler emissionsEventHandler = new EmissionsOnLinkEventHandler(3600); eventsManager.addHandler(emissionsEventHandler); eventsManager.initProcessing(); From b10e1de77509cf5ee1045ff2799c673a13e16e68 Mon Sep 17 00:00:00 2001 From: simei94 <67737999+simei94@users.noreply.github.com> Date: Tue, 25 Jun 2024 17:27:41 +0200 Subject: [PATCH 4/9] debug analysis required for dashboards (#82) * re-arrange tables * switch places and re-name tables * add todo for later * CreateEmissionDashboard -> KelheimSimWrapperRunner * Update MATSim * geotools moved SimpleFeature * debug emission analysis: create injector and install EmissionModule * CreateEmissionDashboard -> KelheimSimWrapperRunner * Update MATSim * geotools moved SimpleFeature * add new / renamed params from single run drt dashboard to avg dashboard analysis * update MATSim * bug fix for cluster * pooling ratio is now occupancy rate * disable NoiseDashboard in KelheimDashboardProvider * clean code --------- Co-authored-by: tschlenther --- pom.xml | 2 +- .../drt/DrtPostProcessingAverageAnalysis.java | 55 +++---- .../drt/DrtServiceQualityAnalysis.java | 2 +- .../matsim/dashboard/AverageDrtDashboard.java | 136 +----------------- .../dashboard/CreateAverageDashboards.java | 4 +- .../dashboard/KelheimDashboardProvider.java | 6 +- .../KelheimSimWrapperRunner.java} | 85 +++++------ .../matsim/drtFare/KelheimDrtFareHandler.java | 2 +- .../matsim/run/prepare/DrtStopsWriter.java | 2 +- .../matsim/run/prepare/PrepareNetwork.java | 2 +- .../run/prepare/PrepareTransitSchedule.java | 2 +- 11 files changed, 76 insertions(+), 222 deletions(-) rename src/main/java/org/matsim/{analysis/CreateEmissionDashboard.java => dashboard/KelheimSimWrapperRunner.java} (68%) diff --git a/pom.xml b/pom.xml index 8dd724e9..64101f47 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ matsim-all - 2025.0-PR3271 + 2025.0-PR3328 diff --git a/src/main/java/org/matsim/analysis/postAnalysis/drt/DrtPostProcessingAverageAnalysis.java b/src/main/java/org/matsim/analysis/postAnalysis/drt/DrtPostProcessingAverageAnalysis.java index 035d0c26..fa2a8cba 100644 --- a/src/main/java/org/matsim/analysis/postAnalysis/drt/DrtPostProcessingAverageAnalysis.java +++ b/src/main/java/org/matsim/analysis/postAnalysis/drt/DrtPostProcessingAverageAnalysis.java @@ -17,6 +17,8 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; import java.time.LocalTime; import java.util.*; @@ -25,11 +27,7 @@ @CommandLine.Command(name = "average-drt", description = "Calculates average drt stats based on several sim runs with different random seeds.") @CommandSpec( requires = {"runs", "mode"}, - produces = {"rides_per_veh_avg_demand_stats.csv", "avg_wait_time_avg_demand_stats.csv", "requests_avg_demand_stats.csv", "avg_total_travel_time_avg_demand_stats.csv", - "rides_avg_demand_stats.csv", "avg_direct_distance_[km]_avg_demand_stats.csv", "rejections_avg_demand_stats.csv", "95th_percentile_wait_time_avg_demand_stats.csv", - "avg_in-vehicle_time_avg_demand_stats.csv", "avg_ride_distance_[km]_avg_demand_stats.csv", "rejection_rate_avg_demand_stats.csv", - "avg_fare_[MoneyUnit]_avg_demand_stats.csv", "total_service_hours_avg_supply_stats.csv", "pooling_ratio_avg_supply_stats.csv", "detour_ratio_avg_supply_stats.csv", - "total_vehicle_mileage_[km]_avg_supply_stats.csv", "empty_ratio_avg_supply_stats.csv", "number_of_stops_avg_supply_stats.csv", "total_pax_distance_[km]_avg_supply_stats.csv", "vehicles_avg_supply_stats.csv"} + produces = {"avg_demand_stats.csv", "avg_supply_stats.csv"} ) public class DrtPostProcessingAverageAnalysis implements MATSimAppCommand { @@ -44,7 +42,6 @@ public class DrtPostProcessingAverageAnalysis implements MATSimAppCommand { private final Map> supplyStats = new HashMap<>(); private final Map demandAvgs = new HashMap<>(); private final Map supplyAvgs = new HashMap<>(); - Map> params = new HashMap<>(); private final CsvOptions csv = new CsvOptions(); @@ -70,11 +67,11 @@ public Integer call() throws Exception { Table demand = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(demandKpiCsv)) .sample(false) - .separator(csv.detectDelimiter(demandKpiCsv)).build()); + .separator(CsvOptions.detectDelimiter(demandKpiCsv)).build()); Table supply = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(supplyKpiCsv)) .sample(false) - .separator(csv.detectDelimiter(supplyKpiCsv)).build()); + .separator(CsvOptions.detectDelimiter(supplyKpiCsv)).build()); // get all demand stats for (int i = 0; i < demand.rowCount(); i++) { @@ -113,38 +110,30 @@ public Integer call() throws Exception { fillAvgMap(demandStats, demandAvgs); fillAvgMap(supplyStats, supplyAvgs); - params.put("avg_demand_stats.csv", List.of("rides_per_veh", "avg_wait_time", "requests", "avg_total_travel_time", "rides", "avg_direct_distance_[km]", - "rejections", "95th_percentile_wait_time", "avg_in-vehicle_time", "avg_ride_distance_[km]", "rejection_rate", "avg_fare_[MoneyUnit]")); - params.put("avg_supply_stats.csv", List.of("total_service_hours", "pooling_ratio", "detour_ratio", "total_vehicle_mileage_[km]", "empty_ratio", "number_of_stops", - "total_pax_distance_[km]", "vehicles")); +// ordered list of params to display them in same order as in single-run DrtDashboard + List orderedDemandParams = List.of("Handled Requests", "Passengers (Pax)", "Avg Group Size", "Pax per veh", "Pax per veh-h", "Pax per veh-km", + "Rejections", "Rejection rate", "Avg. total travel time", "Avg. in-vehicle time", "Avg. wait time", "95th percentile wait time", "Avg. ride distance [km]", + "Avg. direct distance [km]", "Avg. fare [MoneyUnit]"); + List orderedSupplyParams = List.of("Number of stops", "Vehicles", "Total vehicle mileage [km]", "Empty ratio", "Total pax distance [km]", + "Occupancy rate [pax-km/v-km]", "Detour ratio", "Total service hours"); - for (Map.Entry> e : params.entrySet()) { - for (String param : params.get(e.getKey())) { - if (e.getKey().contains("demand")) { - writeFile(e.getKey(), demandAvgs, param); - } else { - writeFile(e.getKey(), supplyAvgs, param); - } - } - } + writeFile("avg_demand_stats.csv", demandAvgs, orderedDemandParams); + writeFile("avg_supply_stats.csv", supplyAvgs, orderedSupplyParams); return 0; } - private void writeFile(String fileName, Map values, String param) throws IOException { - try (CSVPrinter printer = new CSVPrinter(Files.newBufferedWriter(output.getPath(param + "_" + fileName)), CSVFormat.DEFAULT)) { + private void writeFile(String fileName, Map values, List orderedParams) throws IOException { + try (CSVPrinter printer = new CSVPrinter(Files.newBufferedWriter(output.getPath(fileName)), CSVFormat.DEFAULT)) { + DecimalFormat df = new DecimalFormat("#,###.##", new DecimalFormatSymbols(Locale.US)); - printer.printRecord("info", value); +// as of 19.06.24 min and max values are not printed anymore. they will still be calculated though. +// if one wants to include them to dashboard tables one just has to re-include them in this print method. -sme0624 + printer.printRecord("parameter", "mean", "median", "standard deviation"); - for (Map.Entry e : values.entrySet()) { - String transformed = e.getKey().toLowerCase().replace(".", "").replace(" ", "_"); - if (transformed.contains(param)) { - printer.printRecord("mean-" + e.getKey(), e.getValue()[0]); - printer.printRecord("median-" + e.getKey(), e.getValue()[1]); - printer.printRecord("sd-" + e.getKey(), e.getValue()[2]); - printer.printRecord("min-" + e.getKey(), e.getValue()[3]); - printer.printRecord("max-" + e.getKey(), e.getValue()[4]); - } + + for (String param : orderedParams) { + printer.printRecord(param, df.format(values.get(param)[0]), df.format(values.get(param)[1]), df.format(values.get(param)[2])); } } } diff --git a/src/main/java/org/matsim/analysis/postAnalysis/drt/DrtServiceQualityAnalysis.java b/src/main/java/org/matsim/analysis/postAnalysis/drt/DrtServiceQualityAnalysis.java index b1027c2a..6391f16d 100644 --- a/src/main/java/org/matsim/analysis/postAnalysis/drt/DrtServiceQualityAnalysis.java +++ b/src/main/java/org/matsim/analysis/postAnalysis/drt/DrtServiceQualityAnalysis.java @@ -8,6 +8,7 @@ import org.apache.commons.math3.util.Precision; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.geotools.api.feature.simple.SimpleFeature; import org.locationtech.jts.geom.Geometry; import org.matsim.analysis.postAnalysis.traffic.TrafficAnalysis; import org.matsim.api.core.v01.Coord; @@ -35,7 +36,6 @@ import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.VehicleType; import org.matsim.vehicles.VehicleUtils; -import org.opengis.feature.simple.SimpleFeature; import picocli.CommandLine; import java.io.FileWriter; diff --git a/src/main/java/org/matsim/dashboard/AverageDrtDashboard.java b/src/main/java/org/matsim/dashboard/AverageDrtDashboard.java index 82ed8fde..cb467c21 100644 --- a/src/main/java/org/matsim/dashboard/AverageDrtDashboard.java +++ b/src/main/java/org/matsim/dashboard/AverageDrtDashboard.java @@ -39,142 +39,20 @@ public void configure(Header header, Layout layout) { header.description = "Overview for the demand-responsive mode '" + mode + "'. This dashboard shows average values for " + noRuns + " simulation runs. For the results of the specific runs please choose the according directory next to this dashboard.yaml."; -// DEMAND - layout.row("one") - .el(Table.class, (viz, data) -> { - viz.title = "Rides per vehicle"; - viz.dataset = postProcess(data, "rides_per_veh_avg_demand_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }) - .el(Table.class, (viz, data) -> { - viz.title = "Avg wait time"; - viz.dataset = postProcess(data, "avg_wait_time_avg_demand_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }) - .el(Table.class, (viz, data) -> { - viz.title = "Requests"; - viz.dataset = postProcess(data, "requests_avg_demand_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }); - - layout.row("two") - .el(Table.class, (viz, data) -> { - viz.title = "Avg total travel time"; - viz.dataset = postProcess(data, "avg_total_travel_time_avg_demand_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }) - .el(Table.class, (viz, data) -> { - viz.title = "Rides"; - viz.dataset = postProcess(data, "rides_avg_demand_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }) - .el(Table.class, (viz, data) -> { - viz.title = "Avg direct distance [km]"; - viz.dataset = postProcess(data, "avg_direct_distance_[km]_avg_demand_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }); - - layout.row("three") - .el(Table.class, (viz, data) -> { - viz.title = "Rejections"; - viz.dataset = postProcess(data, "rejections_avg_demand_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }) - .el(Table.class, (viz, data) -> { - viz.title = "95th percentile wait time"; - viz.dataset = postProcess(data, "95th_percentile_wait_time_avg_demand_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }) - .el(Table.class, (viz, data) -> { - viz.title = "Avg in-vehicle time"; - viz.dataset = postProcess(data, "avg_in-vehicle_time_avg_demand_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }); - - layout.row("four") - .el(Table.class, (viz, data) -> { - viz.title = "Avg ride distance [km]"; - viz.dataset = postProcess(data, "avg_ride_distance_[km]_avg_demand_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }) - .el(Table.class, (viz, data) -> { - viz.title = "Rejection rate"; - viz.dataset = postProcess(data, "rejection_rate_avg_demand_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }) - .el(Table.class, (viz, data) -> { - viz.title = "Avg fare [MoneyUnit]"; - viz.dataset = postProcess(data, "avg_fare_[MoneyUnit]_avg_demand_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }); - // SUPPLY - supplyTabs(layout); - } - - private void supplyTabs(Layout layout) { - layout.row("six") + layout.row("supply") .el(Table.class, (viz, data) -> { - viz.title = "Total service hours"; - viz.dataset = postProcess(data, "total_service_hours_avg_supply_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }) - .el(Table.class, (viz, data) -> { - viz.title = "Pooling ratio"; - viz.dataset = postProcess(data, "pooling_ratio_avg_supply_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }) - .el(Table.class, (viz, data) -> { - viz.title = "Detour ratio"; - viz.dataset = postProcess(data, "detour_ratio_avg_supply_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }); - - layout.row("seven") - .el(Table.class, (viz, data) -> { - viz.title = "Total vehicle mileage [km]"; - viz.dataset = postProcess(data, "total_vehicle_mileage_[km]_avg_supply_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }) - .el(Table.class, (viz, data) -> { - viz.title = "Empty ratio"; - viz.dataset = postProcess(data, "empty_ratio_avg_supply_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }) - .el(Table.class, (viz, data) -> { - viz.title = "Number of stops"; - viz.dataset = postProcess(data, "number_of_stops_avg_supply_stats.csv"); + viz.title = "Service summary"; + viz.dataset = postProcess(data, "avg_supply_stats.csv"); viz.showAllRows = true; viz.width = 1.; }); - layout.row("eight") - .el(Table.class, (viz, data) -> { - viz.title = "Total pax distance [km]"; - viz.dataset = postProcess(data, "total_pax_distance_[km]_avg_supply_stats.csv"); - viz.showAllRows = true; - viz.width = 1.; - }) + // DEMAND + layout.row("demand") .el(Table.class, (viz, data) -> { - viz.title = "Vehicles"; - viz.dataset = postProcess(data, "vehicles_avg_supply_stats.csv"); + viz.title = "Demand summary"; + viz.dataset = postProcess(data, "avg_demand_stats.csv"); viz.showAllRows = true; viz.width = 1.; }); diff --git a/src/main/java/org/matsim/dashboard/CreateAverageDashboards.java b/src/main/java/org/matsim/dashboard/CreateAverageDashboards.java index d4c1f9e6..cc0dd7f5 100644 --- a/src/main/java/org/matsim/dashboard/CreateAverageDashboards.java +++ b/src/main/java/org/matsim/dashboard/CreateAverageDashboards.java @@ -19,7 +19,7 @@ /** * class to create average dashboards and run the necessary analysis for that. */ -public class CreateAverageDashboards implements MATSimAppCommand { +final class CreateAverageDashboards implements MATSimAppCommand { @CommandLine.Option(names = "--input-path", required = true, description = "Path to directory with run directories.") private String inputPath; @CommandLine.Option(names = "--no-runs", defaultValue = "5", description = "Number of simulation runs to be averaged.") @@ -62,7 +62,7 @@ public Integer call() throws Exception { Arrays.stream(new File(analysisDir).listFiles()) .filter(d -> d.getAbsolutePath().contains(TransportMode.drt)) - .forEach(f -> modes.add(f.getAbsolutePath().substring(f.getAbsolutePath().lastIndexOf("\\") + 1))); + .forEach(f -> modes.add(f.getName())); SimWrapper sw = SimWrapper.create(); diff --git a/src/main/java/org/matsim/dashboard/KelheimDashboardProvider.java b/src/main/java/org/matsim/dashboard/KelheimDashboardProvider.java index 19a478d2..17a1a6c3 100644 --- a/src/main/java/org/matsim/dashboard/KelheimDashboardProvider.java +++ b/src/main/java/org/matsim/dashboard/KelheimDashboardProvider.java @@ -6,7 +6,6 @@ import org.matsim.simwrapper.Dashboard; import org.matsim.simwrapper.DashboardProvider; import org.matsim.simwrapper.SimWrapper; -import org.matsim.simwrapper.dashboard.NoiseDashboard; import org.matsim.simwrapper.dashboard.TravelTimeComparisonDashboard; import org.matsim.simwrapper.dashboard.TripDashboard; @@ -27,8 +26,9 @@ public List getDashboards(Config config, SimWrapper simWrapper) { return List.of( trips, new TravelTimeComparisonDashboard(IOUtils.resolveFileOrResource( "kelheim-v3.0-routes-ref.csv.gz").toString()), - new KelheimEmissionsDashboard(), - new NoiseDashboard() + new KelheimEmissionsDashboard() + //the NoiseAnalysis needs more RAM than the entire simulation, which leads to VM crashes and prevents other analysis to run. We have to run it separately (e.g. with KelheimSimWrapperRunner) +// new NoiseDashboard() ); } diff --git a/src/main/java/org/matsim/analysis/CreateEmissionDashboard.java b/src/main/java/org/matsim/dashboard/KelheimSimWrapperRunner.java similarity index 68% rename from src/main/java/org/matsim/analysis/CreateEmissionDashboard.java rename to src/main/java/org/matsim/dashboard/KelheimSimWrapperRunner.java index 6ea2e798..e6fdc075 100644 --- a/src/main/java/org/matsim/analysis/CreateEmissionDashboard.java +++ b/src/main/java/org/matsim/dashboard/KelheimSimWrapperRunner.java @@ -18,7 +18,7 @@ * * * *********************************************************************** */ -package org.matsim.analysis; +package org.matsim.dashboard; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -26,24 +26,25 @@ import org.matsim.application.ApplicationUtils; import org.matsim.application.MATSimAppCommand; import org.matsim.application.options.ShpOptions; +import org.matsim.contrib.drt.extension.dashboards.DrtDashboardProvider; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.simwrapper.SimWrapper; import org.matsim.simwrapper.SimWrapperConfigGroup; +import org.matsim.simwrapper.dashboard.NoiseDashboard; import picocli.CommandLine; -import java.io.File; import java.io.IOException; import java.nio.file.Path; import java.util.List; @CommandLine.Command( - name = "emissions", + name = "simwrapper", description = "Run emission analysis and create SimWrapper dashboard for existing run output." ) -final class CreateEmissionDashboard implements MATSimAppCommand { +final class KelheimSimWrapperRunner implements MATSimAppCommand { - private static final Logger log = LogManager.getLogger(CreateEmissionDashboard.class); + private static final Logger log = LogManager.getLogger(KelheimSimWrapperRunner.class); @CommandLine.Parameters(arity = "1..*", description = "Path to run output directories for which emission dashboards are to be generated.") private List inputPaths; @@ -53,15 +54,29 @@ final class CreateEmissionDashboard implements MATSimAppCommand { @CommandLine.Option(names = "--base", description = "Optional. " + "Relative path (from each! output directory provided) to main output folder for the base MATSim run. " + - "Will be used to compare emissions per link.", required = false) + "Will be used to compare emissions per link.") private String baseRun; - private CreateEmissionDashboard(){ + @CommandLine.Option(names = "--emissions", defaultValue = "false", description = "create emissions dashboard") + private boolean emissions; + + @CommandLine.Option(names = "--noise", defaultValue = "false", description = "create noise dashboard") + private boolean noise; + + @CommandLine.Option(names = "--drt", defaultValue = "false", description = "create DRT + AV dashboards") + private boolean drt; + + + private KelheimSimWrapperRunner(){ } @Override public Integer call() throws Exception { + if (!drt && !emissions && !noise){ + throw new IllegalArgumentException("you have not configured any dashboard to be created! Use command line parameters!"); + } + for (Path runDirectory : inputPaths) { log.info("Running on {}", runDirectory); @@ -81,10 +96,19 @@ public Integer call() throws Exception { simwrapperCfg.defaultDashboards = SimWrapperConfigGroup.Mode.disabled; simwrapperCfg.defaultParams().mapCenter = "48.91265,11.89223"; - if (baseRun != null){ - sw.addDashboard(new KelheimEmissionsDashboard(baseRun)); - } else { - sw.addDashboard(new KelheimEmissionsDashboard()); + //add dashboards according to command line parameters + if (emissions){ + if (baseRun != null){ + sw.addDashboard(new KelheimEmissionsDashboard(baseRun)); + } else { + sw.addDashboard(new KelheimEmissionsDashboard()); + } + } + if (drt){ + new DrtDashboardProvider().getDashboards(config, sw).forEach(sw::addDashboard); + } + if (noise){ + sw.addDashboard(new NoiseDashboard()); } try { @@ -99,45 +123,8 @@ public Integer call() throws Exception { } public static void main(String[] args) { - new CreateEmissionDashboard().execute(args); + new KelheimSimWrapperRunner().execute(args); } - private static void renameExistingDashboardYAMLs(Path runDirectory) { - // List of files in the folder - File folder = new File(runDirectory.toString()); - File[] files = folder.listFiles(); - - // Loop through all files in the folder - if (files != null) { - for (File file : files) { - if (file.isFile()) { - // Check if the file name starts with "dashboard-" and ends with ".yaml" - if (file.getName().startsWith("dashboard-") && file.getName().endsWith(".yaml")) { - // Get the current file name - String oldName = file.getName(); - - // Extract the number from the file name - String numberPart = oldName.substring(oldName.indexOf('-') + 1, oldName.lastIndexOf('.')); - - // Increment the number by ten - int number = Integer.parseInt(numberPart) + 10; - - // Create the new file name - String newName = "dashboard-" + number + ".yaml"; - - // Create the new File object with the new file name - File newFile = new File(file.getParent(), newName); - - // Rename the file - if (file.renameTo(newFile)) { - log.info("File successfully renamed: " + newName); - } else { - log.info("Error renaming file: " + file.getName()); - } - } - } - } - } - } } diff --git a/src/main/java/org/matsim/drtFare/KelheimDrtFareHandler.java b/src/main/java/org/matsim/drtFare/KelheimDrtFareHandler.java index d689c1d7..25ce692a 100644 --- a/src/main/java/org/matsim/drtFare/KelheimDrtFareHandler.java +++ b/src/main/java/org/matsim/drtFare/KelheimDrtFareHandler.java @@ -3,6 +3,7 @@ import com.google.inject.Inject; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.geotools.api.feature.simple.SimpleFeature; import org.locationtech.jts.geom.Geometry; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.PersonMoneyEvent; @@ -19,7 +20,6 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.utils.geometry.geotools.MGC; import org.matsim.core.utils.gis.GeoFileReader; -import org.opengis.feature.simple.SimpleFeature; import java.net.MalformedURLException; import java.net.URL; diff --git a/src/main/java/org/matsim/run/prepare/DrtStopsWriter.java b/src/main/java/org/matsim/run/prepare/DrtStopsWriter.java index d69d3f85..ab5fdf86 100644 --- a/src/main/java/org/matsim/run/prepare/DrtStopsWriter.java +++ b/src/main/java/org/matsim/run/prepare/DrtStopsWriter.java @@ -5,6 +5,7 @@ import org.apache.commons.csv.CSVRecord; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.geotools.api.feature.simple.SimpleFeature; import org.locationtech.jts.geom.Geometry; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; @@ -18,7 +19,6 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.core.utils.io.MatsimXmlWriter; import org.matsim.run.RunKelheimScenario; -import org.opengis.feature.simple.SimpleFeature; import java.io.FileWriter; import java.io.IOException; diff --git a/src/main/java/org/matsim/run/prepare/PrepareNetwork.java b/src/main/java/org/matsim/run/prepare/PrepareNetwork.java index 3bafb9f9..b22fb53a 100644 --- a/src/main/java/org/matsim/run/prepare/PrepareNetwork.java +++ b/src/main/java/org/matsim/run/prepare/PrepareNetwork.java @@ -2,6 +2,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.geotools.api.feature.simple.SimpleFeature; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; @@ -13,7 +14,6 @@ import org.matsim.application.options.ShpOptions; import org.matsim.core.network.NetworkUtils; import org.matsim.core.utils.geometry.geotools.MGC; -import org.opengis.feature.simple.SimpleFeature; import picocli.CommandLine; import java.util.HashSet; diff --git a/src/main/java/org/matsim/run/prepare/PrepareTransitSchedule.java b/src/main/java/org/matsim/run/prepare/PrepareTransitSchedule.java index a7fd41a8..689e5bf5 100644 --- a/src/main/java/org/matsim/run/prepare/PrepareTransitSchedule.java +++ b/src/main/java/org/matsim/run/prepare/PrepareTransitSchedule.java @@ -1,5 +1,6 @@ package org.matsim.run.prepare; +import org.geotools.api.feature.simple.SimpleFeature; import org.locationtech.jts.geom.Geometry; import org.matsim.api.core.v01.Scenario; import org.matsim.application.MATSimAppCommand; @@ -12,7 +13,6 @@ import org.matsim.pt.transitSchedule.api.TransitSchedule; import org.matsim.pt.transitSchedule.api.TransitScheduleWriter; import org.matsim.pt.transitSchedule.api.TransitStopFacility; -import org.opengis.feature.simple.SimpleFeature; import picocli.CommandLine; import java.util.List; From 2533e751d7653410cd7e09eeceae8e542b42bd0d Mon Sep 17 00:00:00 2001 From: schlenther Date: Tue, 25 Jun 2024 17:48:48 +0200 Subject: [PATCH 5/9] input configs for v3.1 drt+av --- ...1-25pct.kexi-with-av-intermodal.config.xml | 412 ++++++++++++++++++ ...kelheim-v3.1-25pct.kexi-with-av.config.xml | 392 +++++++++++++++++ input/v3.1/kelheim-v3.1-25pct.kexi.config.xml | 46 +- 3 files changed, 824 insertions(+), 26 deletions(-) create mode 100644 input/v3.1/kelheim-v3.1-25pct.kexi-with-av-intermodal.config.xml create mode 100644 input/v3.1/kelheim-v3.1-25pct.kexi-with-av.config.xml diff --git a/input/v3.1/kelheim-v3.1-25pct.kexi-with-av-intermodal.config.xml b/input/v3.1/kelheim-v3.1-25pct.kexi-with-av-intermodal.config.xml new file mode 100644 index 00000000..51301517 --- /dev/null +++ b/input/v3.1/kelheim-v3.1-25pct.kexi-with-av-intermodal.config.xml @@ -0,0 +1,412 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/input/v3.1/kelheim-v3.1-25pct.kexi-with-av.config.xml b/input/v3.1/kelheim-v3.1-25pct.kexi-with-av.config.xml new file mode 100644 index 00000000..e105b8eb --- /dev/null +++ b/input/v3.1/kelheim-v3.1-25pct.kexi-with-av.config.xml @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/input/v3.1/kelheim-v3.1-25pct.kexi.config.xml b/input/v3.1/kelheim-v3.1-25pct.kexi.config.xml index f4c927dc..541495fe 100644 --- a/input/v3.1/kelheim-v3.1-25pct.kexi.config.xml +++ b/input/v3.1/kelheim-v3.1-25pct.kexi.config.xml @@ -1,17 +1,17 @@ - + - + - - - - + + + + @@ -42,7 +42,7 @@ - + @@ -72,7 +72,7 @@ - + @@ -86,7 +86,7 @@ - + @@ -130,13 +130,6 @@ - - @@ -156,7 +149,7 @@ - + @@ -265,11 +258,11 @@ - - - - - + + + + + + @@ -286,10 +280,10 @@ - - - - + + + + From 5204816f273f35c47dd148505dc204b1e22093cc Mon Sep 17 00:00:00 2001 From: schlenther Date: Tue, 9 Jul 2024 12:51:49 +0200 Subject: [PATCH 6/9] analysis summary --- .../drtAnalysis/readValuesFromRunSummaries.R | 280 ++++++++++++++++++ .../VIA-data/KEXI-shiny-dashboard.R | 7 +- 2 files changed, 282 insertions(+), 5 deletions(-) create mode 100644 src/main/R/drtAnalysis/readValuesFromRunSummaries.R diff --git a/src/main/R/drtAnalysis/readValuesFromRunSummaries.R b/src/main/R/drtAnalysis/readValuesFromRunSummaries.R new file mode 100644 index 00000000..2a58d055 --- /dev/null +++ b/src/main/R/drtAnalysis/readValuesFromRunSummaries.R @@ -0,0 +1,280 @@ +library(dplyr) +library(readr) +library(tidyr) +library(ggplot2) # Für das Plotting mit ggplot2 +library(plotly) + +# Funktion zum Extrahieren der Parameter aus dem Ordnernamen +extract_parameters <- function(folder_name, speed) { + # Extrahiere 'area' + area <- strsplit(folder_name, '-')[[1]][1] + + # Extrahiere 'fleetSize' + fleet_size_match <- regmatches(folder_name, regexpr("AV\\d+", folder_name)) + fleet_size <- as.numeric(gsub("AV", "", fleet_size_match)) + + # Setze 'intermodal' + intermodal <- grepl("intermodal", folder_name) + + # Setze 'allDay' + all_day <- grepl("allDay", folder_name) + + return(list(speed = speed, area = area, fleetSize = fleet_size, intermodal = intermodal, allDay = all_day)) +} + +# Funktion zum Einlesen der CSV-Datei und Extrahieren der "mean"-Werte +read_stats <- function(folder_path, file_name) { + csv_path <- file.path(folder_path, "analysis/drt-drt-av", file_name) + + if (file.exists(csv_path)) { + df <- read_csv(csv_path) + mean_values <- df %>% select(parameter, mean) + return(mean_values) + } else { + return(NULL) + } +} + +# Hauptfunktion zum Iterieren durch Unterordner +process_folders <- function(main_folder, speed) { + # Liste aller Unterordner im Hauptordner + subfolders <- list.dirs(main_folder, recursive = FALSE, full.names = FALSE) + + # Initialisiere eine Liste zum Speichern der Ergebnisse + results <- list() + + # Iteriere durch alle Unterordner + for (subfolder in subfolders) { + parameters <- extract_parameters(subfolder, speed) + full_path <- file.path(main_folder, subfolder) + + demand_mean_values <- read_stats(full_path, "avg_demand_stats.csv") + supply_mean_values <- read_stats(full_path, "avg_supply_stats.csv") + + if (!is.null(demand_mean_values) || !is.null(supply_mean_values)) { + if (!is.null(demand_mean_values)) { + demand_mean_values <- demand_mean_values %>% + mutate(type = "demand", + speed = parameters$speed, + area = parameters$area, + fleetSize = parameters$fleetSize, + intermodal = parameters$intermodal, + allDay = parameters$allDay) + } + + if (!is.null(supply_mean_values)) { + supply_mean_values <- supply_mean_values %>% + mutate(type = "supply", + speed = parameters$speed, + area = parameters$area, + fleetSize = parameters$fleetSize, + intermodal = parameters$intermodal, + allDay = parameters$allDay) + } + + combined_values <- bind_rows(demand_mean_values, supply_mean_values) + results[[subfolder]] <- combined_values + } + } + + # Kombiniere alle Ergebnisse in eine Tabelle + final_result <- bind_rows(results) + return(final_result) +} + +############# + +mainDir <- "D:/Projekte/KelRide/runs/v3.1.1/output-KEXI-2.45-AV--0.0/" +#mainDir <- "//sshfs.r/schlenther@cluster.math.tu-berlin.de/net/ils/matsim-kelheim/v3.1.1/output-KEXI-2.45-AV--0.0/" +speeds <- list(3.3, 5, 8.3) + +results <- list() +for (speed in speeds) { + main_folder <- paste(mainDir, "AV-speed-mps-", speed, "/", sep="") + runResults <- process_folders(main_folder, speed) + results[[speed]] <- runResults +} + +results <- bind_rows(results) + + +# Transponiere die Tabelle, um Parameter als Spalten zu setzen +transposed_result <- results %>% + select(speed, area, fleetSize, intermodal, allDay, parameter, mean) %>% + spread(key = parameter, value = mean) + + +# Ergebnisse ausgeben +print(results) +print(transposed_result) + +write_csv(transposed_result, paste(mainDir, "results.csv", sep="")) + +##################################################################### +######PLOTS#### + +# Filtern der Daten für die gewünschten Parameter +plot_data <- results %>% + filter(parameter %in% c("Handled Requests")) + +# Erstellen des interaktiven dreidimensionalen Plots +plot <- plot_ly(plot_data, + x = ~speed, + y = ~fleetSize, + z = ~mean, + color = ~area, + type = "scatter3d", + mode = "markers", + marker = list(size = 5)) %>% + add_markers() %>% + layout(title = "Handled Requests by speed, area and Fleet Size", + scene = list(xaxis = list(title = "Speed"), + yaxis = list(title = "Fleet Size"), + zaxis = list(title = "Handled Requests"))) + +# Plot anzeigen +plot + +# Erstellen des interaktiven dreidimensionalen Plots mit Mesh +plot <- plot_ly(plot_data) %>% + add_mesh(x = ~speed, + y = ~fleetSize, + z = ~mean, + color = ~area, + opacity = 0.6, # Opazität der Flächen + text = ~paste("Area:", area), + colors = c("#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"), # Farben für jede Area + showscale = TRUE) %>% + layout(title = "Handled Requests by speed, fleetSize and area", + scene = list(xaxis = list(title = "Speed"), + yaxis = list(title = "Fleet Size"), + zaxis = list(title = "Mean Handled Requests"))) + +# Plot anzeigen +plot + +mesh_data <- plot_data %>% + group_by(area) %>% + summarise(speed = mean(speed), + fleetSize = mean(fleetSize), + mean = mean(mean)) %>% + arrange(area) + +# Erstellen des interaktiven dreidimensionalen Plots mit Meshes für jede Area +plot <- plot_ly(plot_data) %>% + add_trace(x = ~speed, + y = ~fleetSize, + z = ~mean, + color = ~area, + type = "scatter3d", + mode = "markers", + marker = list(size = 5)) %>% + add_trace(data = mesh_data, + x = ~speed, + y = ~fleetSize, + z = ~mean, + color = ~area, + type = "mesh3d", + opacity = 0.6, # Opazität der Flächen + colorscale = "Viridis", # Farbskala für die Flächen + showscale = TRUE) %>% + layout(title = "Handled Requests by speed, fleetSize and area", + scene = list(xaxis = list(title = "Speed"), + yaxis = list(title = "Fleet Size"), + zaxis = list(title = "Mean Handled Requests"))) + +# Plot anzeigen +plot + + +########################### +plotByConfiguration <- function(parameterStr){ + + # Filtern der Daten für die gewünschten Parameter + plot_data <- results %>% + filter(parameter == parameterStr, + intermodal == TRUE | area == "SAR2023") + + # Erstellen des Facet-Plots + ggplot(plot_data, aes(x = fleetSize, y = mean, color = area, linetype = as.factor(allDay), group = interaction(area, allDay))) + + geom_line(size = 1.2) + + geom_point(size = 3, + #aes(shape = as.factor(intermodal)) + ) + + facet_wrap(~ speed, + scales = "free" + ) + + labs(title = paste(parameterStr, "by Fleet Size, Speed, Area and Service Hours"), + x = "Fleet Size", + y = parameterStr, + color = "Area", + linetype = "All Day" + #,shape = "Intermodal" + ) + + theme_dark() + + theme( + plot.title = element_text(size = 16, face = "bold"), # Titelgröße anpassen + axis.title.x = element_text(size = 14), # X-Achsentitelgröße anpassen + axis.title.y = element_text(size = 14), # Y-Achsentitelgröße anpassen + axis.text = element_text(size = 12), # Achsentextgröße anpassen + legend.title = element_text(size = 14), # Legendentitelgröße anpassen + legend.text = element_text(size = 12), # Legendtextgröße anpassen + strip.text = element_text(size = 12) # Facet-Textgröße anpassen + ) + +} + +unique(results$parameter) +plotByConfiguration("Handled Requests") +plotByConfiguration("Avg. wait time") +plotByConfiguration("Avg. ride distance [km]") +plotByConfiguration("Empty ratio") +plotByConfiguration("Total vehicle mileage [km]") +plotByConfiguration("Avg. fare [MoneyUnit]" ) +plotByConfiguration("Pax per veh-km") + + +##################### +##Zusammenhang wait time und Nachfrage + + handled_requests_data <- results %>% + filter(parameter == "Handled Requests") %>% + select(area, speed, fleetSize, allDay, mean, intermodal) %>% + rename(handled_requests = mean) + + avg_wait_time_data <- results %>% + filter(parameter == "Avg. wait time") %>% + select(area, speed, fleetSize, allDay, mean, intermodal) %>% + rename(avg_wait_time = mean) + + # Zusammenführen der Daten + plot_data <- left_join(handled_requests_data, avg_wait_time_data, by = c("area", "speed", "fleetSize", "allDay", "intermodal")) + + # Erstellen des Facet-Plots + facet_plot <- ggplot(plot_data, aes(x = avg_wait_time, y = handled_requests, color = area, linetype = as.factor(allDay), group = interaction(area, allDay))) + + geom_line(size = 1.2) + + geom_point(size = 3 + #,aes(shape = as.factor(intermodal)) + ) + + facet_wrap(~ speed, scales = "free") + + labs(title = "Handled Requests by Avg. Wait Time, Speed, Area, and All Day", + x = "Avg. Wait Time", + y = "Handled Requests", + color = "Area", + linetype = "All Day" + #,shape = "Intermodal" + ) + + theme_dark() + + theme( + plot.title = element_text(size = 16, face = "bold"), # Titelgröße anpassen + axis.title.x = element_text(size = 14), # X-Achsentitelgröße anpassen + axis.title.y = element_text(size = 14), # Y-Achsentitelgröße anpassen + axis.text = element_text(size = 12), # Achsentextgröße anpassen + legend.title = element_text(size = 14), # Legendentitelgröße anpassen + legend.text = element_text(size = 12), # Legendtextgröße anpassen + strip.text = element_text(size = 12) # Facet-Textgröße anpassen + ) + + # Plot anzeigen + print(facet_plot) + \ No newline at end of file diff --git a/src/main/R/drtDemandAnalysis/VIA-data/KEXI-shiny-dashboard.R b/src/main/R/drtDemandAnalysis/VIA-data/KEXI-shiny-dashboard.R index e24392a2..9e2930cc 100644 --- a/src/main/R/drtDemandAnalysis/VIA-data/KEXI-shiny-dashboard.R +++ b/src/main/R/drtDemandAnalysis/VIA-data/KEXI-shiny-dashboard.R @@ -17,11 +17,8 @@ library(zoo) #for moving averages #input files -data_jan_01_apr_24 <- "D:/svn/shared-svn/projects/KelRide/data/KEXI/Via_data_2024_04_24/Fahrtanfragen-2024-04-24.csv" -data_jan_01_apr_24_fahrerschichten <- "D:/svn/shared-svn/projects/KelRide/data/KEXI/Via_data_2024_04_24/Fahrerschichten-2024-04-24.csv" - -requests_file <- "D:/svn/shared-svn/projects/KelRide/data/KEXI/VIA_data_2024_05_13/Fahrtanfragen-2024-05-13.csv" -shifts_file <- "D:/svn/shared-svn/projects/KelRide/data/KEXI/VIA_data_2024_05_13/Fahrerschichten-2024-05-13.csv" +requests_file <- "D:/shared-svn/projects/KelRide/data/KEXI/VIA_data_2024_06_28/Fahrtanfragen-2024-06-28.csv" +shifts_file <- "D:/shared-svn/projects/KelRide/data/KEXI/VIA_data_2024_06_28/Fahrerschichten-2024-06-28.csv" #parse data data <- read.csv2(requests_file, sep = ",", stringsAsFactors = FALSE, header = TRUE, encoding = "UTF-8") From d57fcfed5d35b18fde3a6157a136100bc465bfe4 Mon Sep 17 00:00:00 2001 From: schlenther Date: Mon, 29 Jul 2024 12:12:46 +0200 Subject: [PATCH 7/9] minor changes in analysis summary --- .../drtAnalysis/readValuesFromRunSummaries.R | 106 +++++----- ...sFromRunSummaries_v3.0.1-fareExperiments.R | 188 ++++++++++++++++++ 2 files changed, 243 insertions(+), 51 deletions(-) create mode 100644 src/main/R/drtAnalysis/readValuesFromRunSummaries_v3.0.1-fareExperiments.R diff --git a/src/main/R/drtAnalysis/readValuesFromRunSummaries.R b/src/main/R/drtAnalysis/readValuesFromRunSummaries.R index 2a58d055..7369b90b 100644 --- a/src/main/R/drtAnalysis/readValuesFromRunSummaries.R +++ b/src/main/R/drtAnalysis/readValuesFromRunSummaries.R @@ -85,7 +85,9 @@ process_folders <- function(main_folder, speed) { ############# mainDir <- "D:/Projekte/KelRide/runs/v3.1.1/output-KEXI-2.45-AV--0.0/" -#mainDir <- "//sshfs.r/schlenther@cluster.math.tu-berlin.de/net/ils/matsim-kelheim/v3.1.1/output-KEXI-2.45-AV--0.0/" + +mainDir <- "E:/matsim-kelheim/v3.1.1/output-KEXI-2.45-AV--0.0/" + speeds <- list(3.3, 5, 8.3) results <- list() @@ -114,26 +116,26 @@ write_csv(transposed_result, paste(mainDir, "results.csv", sep="")) ######PLOTS#### # Filtern der Daten für die gewünschten Parameter -plot_data <- results %>% - filter(parameter %in% c("Handled Requests")) - -# Erstellen des interaktiven dreidimensionalen Plots -plot <- plot_ly(plot_data, - x = ~speed, - y = ~fleetSize, - z = ~mean, - color = ~area, - type = "scatter3d", - mode = "markers", - marker = list(size = 5)) %>% - add_markers() %>% - layout(title = "Handled Requests by speed, area and Fleet Size", - scene = list(xaxis = list(title = "Speed"), - yaxis = list(title = "Fleet Size"), - zaxis = list(title = "Handled Requests"))) +#plot_data <- results %>% +# filter(parameter %in% c("Handled Requests")) -# Plot anzeigen -plot +## Erstellen des interaktiven dreidimensionalen Plots +#plot <- plot_ly(plot_data, +# x = ~speed, +# y = ~fleetSize, +# z = ~mean, +# color = ~area, +# type = "scatter3d", +# mode = "markers", +# marker = list(size = 5)) %>% +# add_markers() %>% +# layout(title = "Handled Requests by speed, area and Fleet Size", +# scene = list(xaxis = list(title = "Speed"), +# yaxis = list(title = "Fleet Size"), +# zaxis = list(title = "Handled Requests"))) +# +## Plot anzeigen +#plot # Erstellen des interaktiven dreidimensionalen Plots mit Mesh plot <- plot_ly(plot_data) %>% @@ -153,38 +155,38 @@ plot <- plot_ly(plot_data) %>% # Plot anzeigen plot -mesh_data <- plot_data %>% - group_by(area) %>% - summarise(speed = mean(speed), - fleetSize = mean(fleetSize), - mean = mean(mean)) %>% - arrange(area) +#mesh_data <- plot_data %>% +# group_by(area) %>% +# summarise(speed = mean(speed), +# fleetSize = mean(fleetSize), +# mean = mean(mean)) %>% +# arrange(area) -# Erstellen des interaktiven dreidimensionalen Plots mit Meshes für jede Area -plot <- plot_ly(plot_data) %>% - add_trace(x = ~speed, - y = ~fleetSize, - z = ~mean, - color = ~area, - type = "scatter3d", - mode = "markers", - marker = list(size = 5)) %>% - add_trace(data = mesh_data, - x = ~speed, - y = ~fleetSize, - z = ~mean, - color = ~area, - type = "mesh3d", - opacity = 0.6, # Opazität der Flächen - colorscale = "Viridis", # Farbskala für die Flächen - showscale = TRUE) %>% - layout(title = "Handled Requests by speed, fleetSize and area", - scene = list(xaxis = list(title = "Speed"), - yaxis = list(title = "Fleet Size"), - zaxis = list(title = "Mean Handled Requests"))) +## Erstellen des interaktiven dreidimensionalen Plots mit Meshes für jede Area +#plot <- plot_ly(plot_data) %>% +# add_trace(x = ~speed, +# y = ~fleetSize, +# z = ~mean, +# color = ~area, +# type = "scatter3d", +# mode = "markers", +# marker = list(size = 5)) %>% +# add_trace(data = mesh_data, +# x = ~speed, +# y = ~fleetSize, +# z = ~mean, +# color = ~area, +# type = "mesh3d", +# opacity = 0.6, # Opazität der Flächen +# colorscale = "Viridis", # Farbskala für die Flächen +# showscale = TRUE) %>% +# layout(title = "Handled Requests by speed, fleetSize and area", +# scene = list(xaxis = list(title = "Speed"), +# yaxis = list(title = "Fleet Size"), +# zaxis = list(title = "Mean Handled Requests"))) -# Plot anzeigen -plot +## Plot anzeigen +#plot ########################### @@ -256,7 +258,9 @@ plotByConfiguration("Pax per veh-km") geom_point(size = 3 #,aes(shape = as.factor(intermodal)) ) + - facet_wrap(~ speed, scales = "free") + + facet_wrap(~ speed + #, scales = "free" + ) + labs(title = "Handled Requests by Avg. Wait Time, Speed, Area, and All Day", x = "Avg. Wait Time", y = "Handled Requests", diff --git a/src/main/R/drtAnalysis/readValuesFromRunSummaries_v3.0.1-fareExperiments.R b/src/main/R/drtAnalysis/readValuesFromRunSummaries_v3.0.1-fareExperiments.R new file mode 100644 index 00000000..acc5a567 --- /dev/null +++ b/src/main/R/drtAnalysis/readValuesFromRunSummaries_v3.0.1-fareExperiments.R @@ -0,0 +1,188 @@ +library(dplyr) +library(readr) +library(tidyr) +library(ggplot2) # Für das Plotting mit ggplot2 +library(plotly) + +# Funktion zum Extrahieren der Parameter aus dem Ordnernamen +extract_parameters <- function(folder_name) { + # Extrahiere 'area' + fares <- strsplit(folder_name, '-')[[1]][2] + + return(list(fares = fares)) +} + +# Funktion zum Einlesen der CSV-Datei und Extrahieren der "mean"-Werte +read_stats <- function(folder_path, file_name) { + csv_path <- file.path(folder_path, "analysis/drt-drt", file_name) + + if (file.exists(csv_path)) { + df <- read_csv(csv_path) + mean_values <- df %>% select(parameter, mean) + return(mean_values) + } else { + return(NULL) + } +} + +# Hauptfunktion zum Iterieren durch Unterordner +process_folders <- function(main_folder) { + # Liste aller Unterordner im Hauptordner + subfolders <- list.dirs(main_folder, recursive = FALSE, full.names = FALSE) + + # Initialisiere eine Liste zum Speichern der Ergebnisse + results <- list() + + # Iteriere durch alle Unterordner + for (subfolder in subfolders) { + parameters <- extract_parameters(subfolder) + full_path <- file.path(main_folder, subfolder) + + demand_mean_values <- read_stats(full_path, "avg_demand_stats.csv") + supply_mean_values <- read_stats(full_path, "avg_supply_stats.csv") + + if (!is.null(demand_mean_values) || !is.null(supply_mean_values)) { + if (!is.null(demand_mean_values)) { + demand_mean_values <- demand_mean_values %>% + mutate(type = "demand", + fares = parameters$fares) + } + + if (!is.null(supply_mean_values)) { + supply_mean_values <- supply_mean_values %>% + mutate(type = "supply", + fares = parameters$fares) + } + + combined_values <- bind_rows(demand_mean_values, supply_mean_values) + results[[subfolder]] <- combined_values + } + } + + # Kombiniere alle Ergebnisse in eine Tabelle + final_result <- bind_rows(results) + return(final_result) +} + +############# + +mainDir <- "D:/Projekte/KelRide/runs/v3.0.1-fare-experiments/output-KEXI-kexi" + +#speeds <- list(3.3, 5, 8.3) +#results <- list() +#for (speed in speeds) { +# main_folder <- paste(mainDir, "AV-speed-mps-", speed, "/", sep="") +# runResults <- process_folders(mainDir) +# results[[speed]] <- runResults +#} + +#results <- bind_rows(results) + + +results <- process_folders(mainDir) + +# Transponiere die Tabelle, um Parameter als Spalten zu setzen +transposed_result <- results %>% + select(fares, parameter, mean) %>% + spread(key = parameter, value = mean) + + +# Ergebnisse ausgeben +print(results) +print(transposed_result) + +write_csv(transposed_result, paste(mainDir, "results.csv", sep="")) + + + + +########################### +plotByConfiguration <- function(parameterStr){ + + # Filtern der Daten für die gewünschten Parameter + plot_data <- results %>% + filter(parameter == parameterStr) + + # Erstellen des Facet-Plots + ggplot(plot_data, aes(x = fares, y = mean)) + + #geom_line(size = 1.2) + + geom_point(size = 3, + #aes(shape = as.factor(intermodal)) + ) + + #facet_wrap(~ speed, + # scales = "free" + #) + + labs(title = paste(parameterStr, "by fare system (conv. KEXI)"), + x = "Fare System", + y = parameterStr, + #color = "Area", + #linetype = "All Day" + #,shape = "Intermodal" + ) + + theme_dark() + + theme( + plot.title = element_text(size = 16, face = "bold"), # Titelgröße anpassen + axis.title.x = element_text(size = 14), # X-Achsentitelgröße anpassen + axis.title.y = element_text(size = 14), # Y-Achsentitelgröße anpassen + axis.text = element_text(size = 12), # Achsentextgröße anpassen + legend.title = element_text(size = 14), # Legendentitelgröße anpassen + legend.text = element_text(size = 12), # Legendtextgröße anpassen + strip.text = element_text(size = 12) # Facet-Textgröße anpassen + ) + +} + +unique(results$parameter) +plotByConfiguration("Rides") +plotByConfiguration("Avg. wait time") +plotByConfiguration("Avg. ride distance [km]") +plotByConfiguration("Empty ratio") +plotByConfiguration("Total vehicle mileage [km]") +plotByConfiguration("Avg. fare [MoneyUnit]" ) +plotByConfiguration("Pax per veh-km") + +##################### +##Zusammenhang wait time und Nachfrage + +handled_requests_data <- results %>% + filter(parameter == "Rides") %>% + select(fares, mean) %>% + rename(handled_requests = mean) + +avg_wait_time_data <- results %>% + filter(parameter == "Avg. wait time") %>% + select(fares, mean) %>% + rename(avg_wait_time = mean) + +# Zusammenführen der Daten +plot_data <- left_join(handled_requests_data, avg_wait_time_data, by = c("fares")) + +# Erstellen des Facet-Plots +facet_plot <- ggplot(plot_data, aes(x = avg_wait_time, y = handled_requests)) + + #geom_line(size = 1.2) + + geom_point(size = 3 + #,aes(shape = as.factor(intermodal)) + ) + + geom_text(aes(label = fares), vjust = -1, hjust = 0.5, size = 3, color = "white") + + #facet_wrap(~ speed, scales = "free") + + labs(title = "Handled Requests by Avg. Wait Time and Fare System (conv. KEXI)", + x = "Avg. Wait Time", + y = "Handled Requests", + #color = "Area", + #linetype = "All Day" + #,shape = "Intermodal" + ) + + theme_dark() + + theme( + plot.title = element_text(size = 16, face = "bold"), # Titelgröße anpassen + axis.title.x = element_text(size = 14), # X-Achsentitelgröße anpassen + axis.title.y = element_text(size = 14), # Y-Achsentitelgröße anpassen + axis.text = element_text(size = 12), # Achsentextgröße anpassen + legend.title = element_text(size = 14), # Legendentitelgröße anpassen + legend.text = element_text(size = 12), # Legendtextgröße anpassen + strip.text = element_text(size = 12) # Facet-Textgröße anpassen + ) + +# Plot anzeigen +print(facet_plot) + From f9710cef226edef0121944caae60e657312f8a45 Mon Sep 17 00:00:00 2001 From: tschlenther Date: Tue, 30 Jul 2024 11:50:30 +0200 Subject: [PATCH 8/9] Update README.md --- README.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 734b2496..20723278 100644 --- a/README.md +++ b/README.md @@ -3,20 +3,18 @@ [![Build Status](https://github.com/matsim-scenarios/matsim-kelheim/actions/workflows/build.yaml/badge.svg)](https://github.com/matsim-scenarios/matsim-kelheim/actions/workflows/build.yaml) ![license](https://img.shields.io/github/license/matsim-scenarios/matsim-kelheim.svg) [![DOI (v3.0)](https://zenodo.org/badge/360167859.svg)](https://zenodo.org/badge/latestdoi/360167859) +[![DOI (v3.1.1)](https://zenodo.org/badge/DOI/10.5281/zenodo.13132756.svg)](https://doi.org/10.5281/zenodo.13132756) ![JDK](https://img.shields.io/badge/JDK-17+-green.svg) ![Kelheim MATSim network and agents](visualization-kelheim.png "Kelheim MATSim network and agents") - - - - ### About this project This repository provides an open MATSim transport model for Kelheim, provided by the [Transport Systems Planning and Transport Telematics group](https://www.tu.berlin/vsp) of [Technische Universität Berlin](http://www.tu-berlin.de). +It is developed as part of the [KelRide](https://kelride.com/) project and thus funded by the [German Federal Minstery for Digital and Transport](https://bmdv.bund.de/DE/Home/home.html). - + This scenario contains a 25pct sample of Kelheim and its surrounding area; road capacities are accordingly reduced. The scenario is calibrated taking into consideration the traffic counts, modal split and mode-specific trip distance distributions. @@ -58,7 +56,7 @@ It can be used by using either of these methods: (Requires either cloning or downloading the repository and java) 1. Open the cmd and go to your project directory -2. Build the scenario using `mvnw package`. Add the option `-Dskiptests=true` in order to skip tests and speed up the process. +2. Build the scenario using `./mvnw package`. Add the option `-DskipTests=true` in order to skip tests and speed up the process. 3. There should be a file directly in the `matsim-kelheim` directory with name approximately as `matsim-kelheim-3.x-SNAPSHOT-.jar`. 4. Run this file from the command line using `java -jar matsim-kelheim-3.x-SNAPSHOT-.jar --help` to see all possible options. 1. For example, one can disable lanes or run smaller sample sizes using the available options @@ -66,7 +64,7 @@ It can be used by using either of these methods: 1. If you want to run the scenario somewhere else, e.g. on a computation cluster, make sure to not only copy the jar but also the 'input' directory and put it right next to the jar. 6. "Open" the output directory. 1. You can drag files into VIA as was already done above. - 2. You can also browse the output directory on vsp.berlin/simwrapper and analyze some of your results with interactive dashboards. + 2. You can also browse the output directory on vsp.berlin/simwrapper and analyse some of your results with interactive dashboards. ---- ### Results and analysis @@ -78,7 +76,7 @@ Here are the most common ways to analyse and visualize the results (and inputs): 1. (use Google for the best experience) 2. Browse your local output directory or [the public matsim-kelheim data repo](https://vsp.berlin/simwrapper/public/de/kelheim) 2. Explore and create many interactive visualisations and dashboards -3. Analysis the output .csv tables using the R language and [the matsim-r package](https://github.com/matsim-vsp/matsim-r) +3. Analyse the output .csv tables using the R language and [the matsim-r package](https://github.com/matsim-vsp/matsim-r) If you have questions, feel free to contact us [(VSP)](https://www.tu.berlin/vsp) any time :) @@ -86,6 +84,7 @@ If you have questions, feel free to contact us [(VSP)](https://www.tu.berlin/vsp ## More information For more information about MATSim, see here: https://www.matsim.org/ + ## Internal documentation Internal documentation can be found here: From b0baffc6b115ea91a692c4e5d113b47342686448 Mon Sep 17 00:00:00 2001 From: tschlenther Date: Tue, 30 Jul 2024 11:53:41 +0200 Subject: [PATCH 9/9] Update CITATION.cff --- CITATION.cff | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index d2263b7c..d2788e95 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -34,8 +34,8 @@ authors: affiliation: Technische Universität Berlin orcid: 'https://orcid.org/0000-0003-2775-6898' url: "https://github.com/matsim-scenarios/matsim-kelheim" -doi: 10.5281/zenodo.8322240 -date-released: 2023-09-06 -year: 2023 -version: 3.1 +doi: 10.5281/zenodo.8322239 +date-released: 2024-06-25 +year: 2024 +version: 3.1.1 license: AGPL-3.0