Skip to content

Commit

Permalink
debug analysis required for dashboards (#82)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
simei94 and tschlenther authored Jun 25, 2024
1 parent 7b95b05 commit b10e1de
Show file tree
Hide file tree
Showing 11 changed files with 76 additions and 222 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<artifactId>matsim-all</artifactId>

<!-- PR-labelled release -->
<version>2025.0-PR3271</version>
<version>2025.0-PR3328</version>

<!-- snapshot == not recommended: rather use PR-labelled release!-->
<!-- <version>16.0-SNAPSHOT</matsim.version>-->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.*;

Expand All @@ -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 {

Expand All @@ -44,7 +42,6 @@ public class DrtPostProcessingAverageAnalysis implements MATSimAppCommand {
private final Map<String, List<Double>> supplyStats = new HashMap<>();
private final Map<String, Double[]> demandAvgs = new HashMap<>();
private final Map<String, Double[]> supplyAvgs = new HashMap<>();
Map<String, List<String>> params = new HashMap<>();

private final CsvOptions csv = new CsvOptions();

Expand All @@ -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++) {
Expand Down Expand Up @@ -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<String> 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<String> 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<String, List<String>> 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<String, Double[]> values, String param) throws IOException {
try (CSVPrinter printer = new CSVPrinter(Files.newBufferedWriter(output.getPath(param + "_" + fileName)), CSVFormat.DEFAULT)) {
private void writeFile(String fileName, Map<String, Double[]> values, List<String> 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<String, Double[]> 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]));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
136 changes: 7 additions & 129 deletions src/main/java/org/matsim/dashboard/AverageDrtDashboard.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.")
Expand Down Expand Up @@ -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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -27,8 +26,9 @@ public List<Dashboard> 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()
);
}

Expand Down
Loading

0 comments on commit b10e1de

Please sign in to comment.