Skip to content

Commit

Permalink
road pricing dashboard first version
Browse files Browse the repository at this point in the history
  • Loading branch information
simei94 committed Mar 21, 2024
1 parent 8f035ff commit d34980b
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.matsim.analysis;
package org.matsim.analysis.roadpricing;

import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
Expand All @@ -14,12 +14,14 @@
import org.matsim.application.options.OutputOptions;
import org.matsim.core.utils.io.IOUtils;
import picocli.CommandLine;
import tech.tablesaw.aggregate.AggregateFunctions;
import tech.tablesaw.api.*;
import tech.tablesaw.io.csv.CsvReadOptions;
import tech.tablesaw.joining.DataFrameJoiner;
import tech.tablesaw.selection.Selection;

import java.io.FileWriter;
import java.io.IOException;
import java.util.*;

import static tech.tablesaw.aggregate.AggregateFunctions.count;
Expand Down Expand Up @@ -79,9 +81,11 @@ public Integer call() throws Exception {
}
Table filtered = moneyEvents.where(Selection.with(idx.toIntArray()));

double totalToll = (double) filtered.summarize("amount", AggregateFunctions.sum).apply().column("Sum [amount]").get(0);

try (CSVPrinter printer = new CSVPrinter(new FileWriter(output.getPath("roadPricing_tolled_agents.csv").toString()), CSVFormat.DEFAULT)) {
printer.printRecord("numberOfTolledAgents");
printer.printRecord(filtered.rowCount());
printer.printRecord("total toll paid [MXN]", totalToll, "paid_FILL1_wght400_GRAD0_opsz48.png", "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/mx/mexico-city/mexico-city-v1.0/input/roadPricing/");
printer.printRecord("number of tolled agents", filtered.rowCount(), "tag_FILL1_wght400_GRAD0_opsz48.png", "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/mx/mexico-city/mexico-city-v1.0/input/roadPricing/");
}

Table joined = new DataFrameJoiner(moneyEvents, person).inner(persons);
Expand Down Expand Up @@ -151,6 +155,7 @@ private void writeIncomeDistr(Table joined) {

if (income < 0) {
log.error("income {} is negative. This should not happen!", income);
throw new IllegalArgumentException();
}

for (Map.Entry<String, Range<Integer>> e : labels.entrySet()) {
Expand All @@ -164,20 +169,46 @@ private void writeIncomeDistr(Table joined) {

Table aggr = joined.summarize(person, count).by(incomeGroup);

// how to sort rows here? this does not work! Using workaround instead. -sme0324
DoubleColumn shareCol = aggr.numberColumn(1).divide(aggr.numberColumn(1).sum()).setName(this.share);
aggr.addColumns(shareCol);
aggr.sortOn(this.share);

Table result = Table.create();
result.addColumns(StringColumn.create(incomeGroup), DoubleColumn.create("Count [person]"), DoubleColumn.create(this.share));
List<String> incomeDistr = new ArrayList<>();

for (int i = 0; i < aggr.rowCount() - 1; i++) {
Row row = aggr.row(i);
for (String k : labels.keySet()) {
for (int i = 0; i < aggr.rowCount() - 1; i++) {
Row row = aggr.row(i);
if (row.getString(incomeGroup).equals(k)) {
incomeDistr.add(k + "," + row.getDouble("Count [person]") + "," + row.getDouble("share"));
break;
}
}
}

if (!row.getString(incomeGroup).equals("")) {
result.addRow(i, aggr);
incomeDistr.sort(Comparator.comparingInt(RoadPricingAnalysis::getLowerBound));

CSVFormat format = CSVFormat.DEFAULT.builder()
.setQuote(null)
.setDelimiter(',')
.setRecordSeparator("\r\n")
.build();


try (CSVPrinter printer = new CSVPrinter(new FileWriter(output.getPath("roadPricing_income_groups.csv").toString()), format)) {
for (String s : incomeDistr) {
printer.printRecord(s);
}
} catch (IOException e) {
throw new IllegalArgumentException();
}
}

private static int getLowerBound(String s) {
String regex = " - ";
if (s.contains("+")) {
regex = "\\+";
}
result.write().csv(output.getPath("roadPricing_income_groups.csv").toFile());
return Integer.parseInt(s.split(regex)[0]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,20 @@
*/
public class MexicoCityDashboardProvider implements DashboardProvider {

String roadPricingAreaPath;

@Override
public List<Dashboard> getDashboards(Config config, SimWrapper simWrapper) {

// TripDashboard trips = new TripDashboard("mode_share_ref.csv", "mode_share_per_dist_ref.csv", "mode_users_ref.csv");
TripDashboard trips = new TripDashboard("mode_share_ref.csv", null, null);

return List.of(trips);
return List.of(trips, new RoadPricingDashboard(roadPricingAreaPath));
}

/**
* set path to shp file of road pricing area.
*/
public void setRoadPricingAreaPath(String roadPricingAreaPath) {
this.roadPricingAreaPath = roadPricingAreaPath;
}
}
77 changes: 77 additions & 0 deletions src/main/java/org/matsim/dashboard/RoadPricingDashboard.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package org.matsim.dashboard;

import org.matsim.analysis.roadpricing.RoadPricingAnalysis;
import org.matsim.prepare.MexicoCityUtils;
import org.matsim.simwrapper.Dashboard;
import org.matsim.simwrapper.Header;
import org.matsim.simwrapper.Layout;
import org.matsim.simwrapper.viz.*;

import java.util.List;

/**
* Shows information about an optional road pricing policy case.
*/
public class RoadPricingDashboard implements Dashboard {
String roadPricingAreaPath;
String share = "share";

RoadPricingDashboard(String roadPricingAreaPath) {
this.roadPricingAreaPath = roadPricingAreaPath;
}
@Override
public void configure(Header header, Layout layout) {
header.title = "Road Pricing";
header.description = "General information about the simulated road pricing policy case.";

layout.row("first").el(Tile.class, (viz, data) -> {
viz.dataset = data.compute(RoadPricingAnalysis.class, "roadPricing_tolled_agents.csv");
viz.height = 0.1;
});

layout.row("second")
.el(Bar.class, (viz, data) -> {
viz.title = "Tolled agents";
viz.description = "income groups";
viz.stacked = false;
viz.dataset = data.compute(RoadPricingAnalysis.class, "roadPricing_income_groups.csv");
viz.x = "incomeGroup";
viz.xAxisName = "income group";
viz.yAxisName = share;
viz.columns = List.of(share);
})
.el(Bar.class, (viz, data) -> {
viz.title = "Tolled agents";
viz.description = "per hour";
viz.stacked = false;
viz.dataset = data.compute(RoadPricingAnalysis.class, "roadPricing_daytime_groups.csv");
viz.x = "hour";
viz.xAxisName = "hour";
viz.yAxisName = share;
viz.columns = List.of(share);
});

layout.row("third")
.el(Hexagons.class, (viz, data) -> {

viz.title = "Tolled agents home locations";
viz.center = data.context().getCenter();
viz.zoom = data.context().mapZoomLevel;
viz.height = 7.5;
viz.width = 2.0;

viz.file = data.compute(RoadPricingAnalysis.class, "roadPricing_tolled_agents_home_locations.csv");
viz.projection = MexicoCityUtils.CRS;
viz.addAggregation("home locations", "person", "home_x", "home_y");
})
.el(MapPlot.class, (viz, data) -> {
viz.title = "Toll area";
viz.center = data.context().getCenter();
viz.zoom = data.context().mapZoomLevel;
viz.height = 7.5;
viz.width = 2.0;
// TODO: parsing of roadPricingAreaPath does not work yet
viz.setShape(roadPricingAreaPath);
});
}
}
9 changes: 9 additions & 0 deletions src/main/java/org/matsim/run/RunMexicoCityScenario.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@
import org.matsim.core.replanning.annealing.ReplanningAnnealerConfigGroup;
import org.matsim.core.router.AnalysisMainModeIdentifier;
import org.matsim.core.scoring.functions.ScoringParametersForPerson;
import org.matsim.dashboard.MexicoCityDashboardProvider;
import org.matsim.prepare.*;
import org.matsim.prepare.network.CreateMexicoCityNetworkFromSumo;
import org.matsim.prepare.network.PrepareNetwork;
import org.matsim.prepare.opt.RunCountOptimization;
import org.matsim.prepare.opt.SelectPlansFromIndex;
import org.matsim.prepare.population.*;
import org.matsim.simwrapper.DashboardProvider;
import org.matsim.simwrapper.SimWrapperConfigGroup;
import org.matsim.simwrapper.SimWrapperModule;
import org.matsim.vehicles.VehicleType;
Expand Down Expand Up @@ -276,6 +278,13 @@ public void install() {
if (MexicoCityUtils.isDefined(RoadPricingOptions.roadPricingAreaPath)) {
install(new RoadPricingModule());

MexicoCityDashboardProvider provider = new MexicoCityDashboardProvider();
provider.setRoadPricingAreaPath(RoadPricingOptions.roadPricingAreaPath.toString());

bind(DashboardProvider.class).toInstance(provider);



// use own RoadPricingControlerListener, which throws person money events by multiplying the toll (factor) by the agent's income
if (RoadPricingOptions.roadPricingType.equals(RoadPricingOptions.RoadPricingType.RELATIVE_TO_INCOME)) {
if (!MexicoCityUtils.isDefined(incomeAreaPath)) {
Expand Down

0 comments on commit d34980b

Please sign in to comment.