diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java b/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java index eb76c273c61..c5927fcdb04 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java @@ -110,8 +110,8 @@ public Integer call() throws Exception { private Config prepareConfig() { Config config = ConfigUtils.loadConfig(ApplicationUtils.matchInput("config.xml", input.getRunDirectory()).toAbsolutePath().toString(), new NoiseConfigGroup()); - //it is important to match "output_vehicles" because otherwise dvrpVehicle files might be matched and the code crashes later - config.vehicles().setVehiclesFile(ApplicationUtils.matchInput("output_vehicles", input.getRunDirectory()).toAbsolutePath().toString()); + //it is important to match "output_vehicles.xml.gz" specifically, because otherwise dvrpVehicle files might be matched and the code crashes later + config.vehicles().setVehiclesFile(ApplicationUtils.matchInput("output_vehicles.xml.gz", input.getRunDirectory()).toAbsolutePath().toString()); config.network().setInputFile(ApplicationUtils.matchInput("network", input.getRunDirectory()).toAbsolutePath().toString()); config.transit().setTransitScheduleFile(null); config.transit().setVehiclesFile(null); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/CreateDrtDashboard.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/CreateDrtDashboard.java new file mode 100644 index 00000000000..382ee1214d5 --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/CreateDrtDashboard.java @@ -0,0 +1,87 @@ +/* *********************************************************************** * + * 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.contrib.drt.extension.dashboards; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.application.ApplicationUtils; +import org.matsim.application.MATSimAppCommand; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.simwrapper.SimWrapper; +import org.matsim.simwrapper.SimWrapperConfigGroup; +import picocli.CommandLine; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; + +@CommandLine.Command( + name = "drt", + description = "Run DRT analysis and create SimWrapper dashboard for existing run output." +) +final class CreateDrtDashboard implements MATSimAppCommand { + + private static final Logger log = LogManager.getLogger(CreateDrtDashboard.class); + + @CommandLine.Parameters(arity = "1..*", description = "Path to run output directories for which DRT dashboards are to be generated.") + private List inputPaths; + + private CreateDrtDashboard(){ + } + + @Override + public Integer call() throws Exception { + + for (Path runDirectory : inputPaths) { + log.info("Running on {}", runDirectory); + + Path configPath = ApplicationUtils.matchInput("config.xml", runDirectory); + Config config = ConfigUtils.loadConfig(configPath.toString()); + SimWrapper sw = SimWrapper.create(config); + + SimWrapperConfigGroup simwrapperCfg = ConfigUtils.addOrGetModule(config, SimWrapperConfigGroup.class); + + //skip default dashboards + simwrapperCfg.defaultDashboards = SimWrapperConfigGroup.Mode.disabled; + + //add drt dashboards + new DrtDashboardProvider().getDashboards(config, sw).forEach(sw::addDashboard); + + try { + //append dashboard to existing ones + boolean append = true; + sw.generate(runDirectory, append); + sw.run(runDirectory); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + return 0; + } + + public static void main(String[] args) { + new CreateDrtDashboard().execute(args); + + } + +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtAnalysisPostProcessing.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtAnalysisPostProcessing.java index a8f9e8eabb0..d37eac13219 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtAnalysisPostProcessing.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtAnalysisPostProcessing.java @@ -111,7 +111,7 @@ private static Table prepareSupplyKPITable(Table vehicleStats) { .round() .setName("Total pax distance [km]")); - tableSupplyKPI.column("d_p/d_t").setName("Pooling ratio"); + tableSupplyKPI.column("d_p/d_t").setName("Occupancy rate [pax-km/v-km]"); tableSupplyKPI.column("l_det").setName("Detour ratio"); tableSupplyKPI.column("emptyRatio").setName("Empty ratio"); @@ -122,17 +122,19 @@ private static void printDemandKPICSV(Table customerStats, Table tableSupplyKPI, double rides = getLastDoubleValue(customerStats, "rides"); double rejections = getLastDoubleValue(customerStats, "rejections"); double requests = rides + rejections; + double pax = getLastDoubleValue(customerStats, "rides_pax"); DecimalFormat df = new DecimalFormat("#,###.##", new DecimalFormatSymbols(Locale.US)); try (CSVPrinter csv = new CSVPrinter(Files.newBufferedWriter(output), CSVFormat.DEFAULT)) { csv.printRecord("Info", "value"); - csv.printRecord("Requests", requests); - csv.printRecord("Rides", rides); - csv.printRecord("Rides per veh", df.format(rides / ((DoubleColumn) tableSupplyKPI.column("vehicles")).get(0))); - csv.printRecord("Rides per veh-h", df.format(rides / ((DoubleColumn) tableSupplyKPI.column("total service hours")).get(0))); - csv.printRecord("Rides per veh-km", df.format(rides / ((DoubleColumn) tableSupplyKPI.column("total vehicle mileage [km]")).get(0))); + csv.printRecord("Handled Requests", requests); + csv.printRecord("Passengers (Pax)", pax); + csv.printRecord("Avg Group Size", df.format((getLastDoubleValue(customerStats, "groupSize_mean")))); + csv.printRecord("Pax per veh", df.format(pax / ((DoubleColumn) tableSupplyKPI.column("vehicles")).get(0))); + csv.printRecord("Pax per veh-h", df.format(pax / ((DoubleColumn) tableSupplyKPI.column("total service hours")).get(0))); + csv.printRecord("Pax per veh-km", df.format(pax / ((DoubleColumn) tableSupplyKPI.column("total vehicle mileage [km]")).get(0))); csv.printRecord("Rejections", rejections); csv.printRecord("Rejection rate", getLastDoubleValue(customerStats, "rejectionRate")); csv.printRecord("Avg. total travel time", LocalTime.ofSecondOfDay(getLastDoubleValue(customerStats, "totalTravelTime_mean").longValue())); @@ -168,28 +170,13 @@ public Integer call() throws Exception { //read vehicle stats Path vehicleStatsPath = ApplicationUtils.matchInput("drt_vehicle_stats_" + drtMode + ".csv", input.getRunDirectory()); Table vehicleStats = Table.read().csv(CsvReadOptions.builder(vehicleStatsPath.toFile()) - .columnTypesPartial(Map.of("vehicles", ColumnType.DOUBLE, - "totalDistance", ColumnType.DOUBLE, - "emptyRatio", ColumnType.DOUBLE, - "totalServiceDuration", ColumnType.DOUBLE, - "d_p/d_t", ColumnType.DOUBLE, - "totalPassengerDistanceTraveled", ColumnType.DOUBLE)) + .columnTypes(columnHeader -> columnHeader.equals("runId") ? ColumnType.STRING : ColumnType.DOUBLE) .separator(';').build()); //read customer stats Path customerStatsPath = ApplicationUtils.matchInput("drt_customer_stats_" + drtMode + ".csv", input.getRunDirectory()); Table customerStats = Table.read().csv(CsvReadOptions.builder(customerStatsPath.toFile()) - .columnTypesPartial(Map.of( - "rides", ColumnType.DOUBLE, - "wait_average", ColumnType.DOUBLE, - "wait_p95", ColumnType.DOUBLE, - "inVehicleTravelTime_mean", ColumnType.DOUBLE, - "distance_m_mean", ColumnType.DOUBLE, - "directDistance_m_mean", ColumnType.DOUBLE, - "totalTravelTime_mean", ColumnType.DOUBLE, - "fareAllReferences_mean", ColumnType.DOUBLE, - "rejections", ColumnType.DOUBLE, - "rejectionRate", ColumnType.DOUBLE)) + .columnTypes(columnHeader -> columnHeader.equals("runId") ? ColumnType.STRING : ColumnType.DOUBLE) .separator(';').build()); Table tableSupplyKPI = Table.create("supplyKPI"); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtDashboard.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtDashboard.java index b7e1aeda0f9..a62f46a1ebc 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtDashboard.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtDashboard.java @@ -386,7 +386,7 @@ public void configure(Header header, Layout layout) { .el(Line.class, (viz, data) -> { viz.title = "Relative Statistics per iteration"; viz.dataset = data.output("*vehicle_stats_" + drtConfigGroup.mode + ".csv"); - viz.description = "Pooling ratio (Pax distance / Vehicle mileage), Detour ratio, and Empty Ratio"; + viz.description = "Occupancy rate (Pax distance / Vehicle mileage), Detour ratio, and Empty Ratio"; viz.x = "iteration"; viz.columns = List.of("d_p/d_t", "l_det", "emptyRatio"); viz.legendName = List.of("Pooling ratio", "Detour ratio", "Empty Ratio"); diff --git a/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/NoiseDashboardTests.java b/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/NoiseDashboardTests.java index 58c3182b5ba..6ca2a08cee3 100644 --- a/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/NoiseDashboardTests.java +++ b/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/NoiseDashboardTests.java @@ -1,5 +1,6 @@ package org.matsim.simwrapper.dashboard; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.application.MATSimApplication; @@ -15,6 +16,7 @@ import java.net.URL; +import java.nio.file.Path; public class NoiseDashboardTests { @@ -24,6 +26,8 @@ public class NoiseDashboardTests { @Test void generate() { + Path out = Path.of(utils.getOutputDirectory(), "analysis", "noise"); + Config config = TestScenario.loadConfig(utils); config.global().setCoordinateSystem("EPSG:25832"); @@ -34,11 +38,14 @@ void generate() { simWrapperConfigGroup.defaultParams().shp = IOUtils.extendUrl(kelheim, "area/area.shp").toString(); - SimWrapper sw = SimWrapper.create(config).addDashboard(new NoiseDashboard()); Controler controler = MATSimApplication.prepare(new TestScenario(sw), config); - controler.run(); + + Assertions.assertThat(out) + .isDirectoryContaining("glob:**emission_per_day.csv") + .isDirectoryContaining("glob:**immission_per_day.avro") + .isDirectoryContaining("glob:**immission_per_hour.avro"); } }