Skip to content

Commit

Permalink
add misc summary stats (#1085)
Browse files Browse the repository at this point in the history
* add misc summary stats

* add null check and change return syntax

* refactoring

* bug fix: wrong field used

* refactor: reuse code

* add totalHoursOfVehicleTrafficDelay in summary stats.

* add summary stats for averagePTWaitingTime

* add bus crowding in summary stats

* reset bus crowding

* add averageTripExpenditure in summary stats

* fixed cost aggregation

* fixed PTCrowding (bus)

* renamed to totalNetCost

* fixed warnings

* reset ptWaiting against personId

* fixed average and update labels

* hoursTraveled should be renamed to travelDurationInSec, as this is not in hours

* remove / 3600 for busCrowding

* fixed hard coding of modes

* fixed hard coding of modes

* rename _person

* fixed warnings and format

* create summary stats for average vehicle delay for motorized leg. (#1095)

* fixed numOfTimesBusTaken in busCrowding

* changed buses list to set

* fixed averageVehicleDelay

* fixed delay stat variable name

* fixed delay stats calculation

* fix n/0 issue

* fix totalVehicles for averageDelays
  • Loading branch information
rajnikantsh authored and zishanbilal committed Dec 31, 2018
1 parent 20f95e9 commit 067a827
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 38 deletions.
2 changes: 1 addition & 1 deletion src/main/java/beam/analysis/StatsFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ private BeamAnalysis createStats(StatsType statsType) {
case DeadHeading:
return new DeadHeadingAnalysis(writeGraphs);
case VehicleHoursTraveled:
return new VehicleTravelTimeAnalysis(beamServices.vehicleTypes().keySet());
return new VehicleTravelTimeAnalysis(beamServices.matsimServices().getScenario(), beamServices.vehicleTypes().keySet());
case MotorizedVehicleMilesTraveled:
return new MotorizedVehicleMilesTraveledAnalysis(beamServices.vehicleTypes().keySet());
case NumberOfVehicles:
Expand Down
62 changes: 45 additions & 17 deletions src/main/java/beam/analysis/plots/RideHailWaitingAnalysis.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package beam.analysis.plots;

import beam.agentsim.events.ModeChoiceEvent;
import beam.analysis.IterationSummaryAnalysis;
import beam.analysis.plots.modality.RideHailDistanceRowModel;
import beam.sim.OutputDataDescription;
import beam.sim.config.BeamConfig;
import beam.utils.OutputDataDescriptor;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.data.category.CategoryDataset;
Expand All @@ -23,16 +22,21 @@
import java.io.IOException;
import java.util.*;

import static java.lang.Integer.max;

/**
* @author abid
*/
public class RideHailWaitingAnalysis implements GraphAnalysis {
public class RideHailWaitingAnalysis implements GraphAnalysis, IterationSummaryAnalysis {

public static final String RIDE_HAIL = "ride_hail";
public static final String WALK_TRANSIT = "walk_transit";

public RideHailWaitingAnalysis(StatsComputation<Tuple<List<Double>, Map<Integer, List<Double>>>, Tuple<Map<Integer, Map<Double, Integer>>, double[][]>> statComputation) {
this.statComputation = statComputation;
}

public static class WaitingStatsComputation implements StatsComputation<Tuple<List<Double>, Map<Integer, List<Double>>>, Tuple<Map<Integer, Map<Double, Integer>>, double[][]>> {
public static class WaitingStatsComputation implements StatsComputation<Tuple<List<Double>, Map<Integer, List<Double>>>, Tuple<Map<Integer, Map<Double, Integer>>, double[][]>> {

@Override
public Tuple<Map<Integer, Map<Double, Integer>>, double[][]> compute(Tuple<List<Double>, Map<Integer, List<Double>>> stat) {
Expand Down Expand Up @@ -124,15 +128,18 @@ private double[][] buildModesFrequencyDataset(Map<Integer, Map<Double, Integer>>
private boolean writeGraph;
private List<RideHailWaitingIndividualStat> rideHailWaitingIndividualStatList = new ArrayList<>();
private Map<String, Event> rideHailWaiting = new HashMap<>();
private Map<String, Double> ptWaiting = new HashMap<>();
private Map<Integer, List<Double>> hoursTimesMap = new HashMap<>();
private double waitTimeSum = 0; //sum of all wait times experienced by customers
private int rideHailCount = 0; //later used to calculate average wait time experienced by customers
private double totalPTWaitingTime = 0.0;
private int numOfTrips = 0;
private final StatsComputation<Tuple<List<Double>, Map<Integer, List<Double>>>, Tuple<Map<Integer, Map<Double, Integer>>, double[][]>> statComputation;

private static int numberOfTimeBins = 30;

public RideHailWaitingAnalysis(StatsComputation<Tuple<List<Double>, Map<Integer, List<Double>>>, Tuple<Map<Integer, Map<Double, Integer>>, double[][]>> statComputation,
BeamConfig beamConfig){
BeamConfig beamConfig) {
this.statComputation = statComputation;
this.writeGraph = beamConfig.beam().outputs().writeGraphs();
final int timeBinSize = beamConfig.beam().outputs().stats().binSize();
Expand All @@ -147,7 +154,9 @@ public RideHailWaitingAnalysis(StatsComputation<Tuple<List<Double>, Map<Integer,
@Override
public void resetStats() {
waitTimeSum = 0;
numOfTrips = 0;
rideHailCount = 0;
totalPTWaitingTime = 0.0;
rideHailWaiting.clear();
hoursTimesMap.clear();
rideHailWaitingIndividualStatList.clear();
Expand All @@ -159,40 +168,51 @@ public void processStats(Event event) {
Map<String, String> eventAttributes = event.getAttributes();
if (event instanceof ModeChoiceEvent) {
String mode = eventAttributes.get("mode");
if (mode.equalsIgnoreCase("ride_hail")) {

if (mode.equalsIgnoreCase(RIDE_HAIL)) {

ModeChoiceEvent modeChoiceEvent = (ModeChoiceEvent) event;
Id<Person> personId = modeChoiceEvent.getPersonId();
rideHailWaiting.put(personId.toString(), event);
}
if (mode.equalsIgnoreCase(WALK_TRANSIT)) {

ModeChoiceEvent modeChoiceEvent = (ModeChoiceEvent) event;
Id<Person> personId = modeChoiceEvent.getPersonId();
ptWaiting.put(personId.toString(), event.getTime());
}

} else if (event instanceof PersonEntersVehicleEvent) {

PersonEntersVehicleEvent personEntersVehicleEvent = (PersonEntersVehicleEvent) event;
Id<Person> personId = personEntersVehicleEvent.getPersonId();
String _personId = personId.toString();
String pId = personId.toString();

// This rideHailVehicle check is put here again to remove the non rideHail vehicleId which were coming due the
// another occurrence of modeChoice event because of replanning event.
if (rideHailWaiting.containsKey(personId.toString()) && eventAttributes.get("vehicle").contains("rideHailVehicle")) {

ModeChoiceEvent modeChoiceEvent = (ModeChoiceEvent) rideHailWaiting.get(_personId);
ModeChoiceEvent modeChoiceEvent = (ModeChoiceEvent) rideHailWaiting.get(pId);
double difference = personEntersVehicleEvent.getTime() - modeChoiceEvent.getTime();
processRideHailWaitingTimes(modeChoiceEvent, difference);

// Building the RideHailWaitingIndividualStat List
String __vehicleId = eventAttributes.get(PersonEntersVehicleEvent.ATTRIBUTE_VEHICLE);
String __personId = eventAttributes.get(PersonEntersVehicleEvent.ATTRIBUTE_PERSON);

RideHailWaitingIndividualStat rideHailWaitingIndividualStat = new RideHailWaitingIndividualStat();
rideHailWaitingIndividualStat.time = modeChoiceEvent.getTime();
rideHailWaitingIndividualStat.personId = __personId;
rideHailWaitingIndividualStat.vehicleId = __vehicleId;
rideHailWaitingIndividualStat.personId = eventAttributes.get(PersonEntersVehicleEvent.ATTRIBUTE_PERSON);
rideHailWaitingIndividualStat.vehicleId = eventAttributes.get(PersonEntersVehicleEvent.ATTRIBUTE_VEHICLE);
rideHailWaitingIndividualStat.waitingTime = difference;
rideHailWaitingIndividualStatList.add(rideHailWaitingIndividualStat);


// Remove the personId from the list of ModeChoiceEvent
rideHailWaiting.remove(_personId);
rideHailWaiting.remove(pId);
}
// added summary stats for totalPTWaitingTime
if (ptWaiting.containsKey(pId) && eventAttributes.get("vehicle").contains("body")) {
totalPTWaitingTime += event.getTime() - ptWaiting.get(pId);
numOfTrips++;
ptWaiting.remove(pId);
}
}
}
Expand All @@ -216,6 +236,14 @@ public void createGraph(IterationEndsEvent event) throws IOException {
writeRideHailWaitingIndividualStatCSV(event.getIteration());
}

@Override
public Map<String, Double> getSummaryStats() {
return new HashMap<String, Double>() {{
put("averageRideHailWaitTimeInSec", waitTimeSum / max(rideHailCount, 1));
put("averagePTWaitingTimeInSec", totalPTWaitingTime / max(numOfTrips, 1));
}};
}

private void writeRideHailWaitingIndividualStatCSV(int iteration) {

String csvFileName = GraphsStatsAgentSimEventsListener.CONTROLLER_IO.getIterationFilename(iteration, rideHailIndividualWaitingTimesFileBaseName + ".csv");
Expand Down Expand Up @@ -245,7 +273,7 @@ private void writeRideHailWaitingIndividualStatCSV(int iteration) {
private void processRideHailWaitingTimes(Event event, double waitingTime) {
int hour = GraphsStatsAgentSimEventsListener.getEventHour(event.getTime());

waitingTime = waitingTime/60;
waitingTime = waitingTime / 60;

List<Double> timeList = hoursTimesMap.get(hour);
if (timeList == null) {
Expand Down Expand Up @@ -329,9 +357,9 @@ private List<String> getLegends(List<Double> categories) {
for (Double category : categories) {

double legend = getRoundedCategoryUpperBound(category);
if(legend > 60 )
if (legend > 60)
legends.add("60+");
else{
else {
legends.add(category.intValue() + "min");
}

Expand Down
12 changes: 11 additions & 1 deletion src/main/java/beam/analysis/summary/PersonCostAnalysis.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
import beam.analysis.IterationSummaryAnalysis;
import beam.router.Modes;
import org.matsim.api.core.v01.events.Event;
import org.matsim.api.core.v01.events.PersonDepartureEvent;

import java.util.HashMap;
import java.util.Map;

public class PersonCostAnalysis implements IterationSummaryAnalysis {
private Map<String, Double> personCostByCostType = new HashMap<>();
private Map<String,Double> personCostByCostType = new HashMap<>();
private String[] costTypes = {"Cost", "Incentive", "Toll"};
private int numberOfTrips = 0;
private double totalNetCost = 0.0;

@Override
public void processStats(Event event) {
Expand All @@ -22,6 +25,7 @@ public void processStats(Event event) {
switch (costType) {
case "Cost":
cost = Double.parseDouble(attributes.get(PersonCostEvent.ATTRIBUTE_NET_COST));
totalNetCost += cost;
break;
case "Incentive":
cost = Double.parseDouble(attributes.get(PersonCostEvent.ATTRIBUTE_INCENTIVE));
Expand All @@ -34,15 +38,21 @@ public void processStats(Event event) {
personCostByCostType.merge(statType, cost, (d1, d2) -> d1 + d2);
}
}
if (event instanceof PersonDepartureEvent || event.getEventType().equalsIgnoreCase(PersonDepartureEvent.EVENT_TYPE)) {
numberOfTrips++;
}
}

@Override
public void resetStats() {
personCostByCostType.clear();
numberOfTrips = 0;
totalNetCost = 0;
}

@Override
public Map<String, Double> getSummaryStats() {
personCostByCostType.put("averageTripExpenditure", totalNetCost / numberOfTrips);
Modes.BeamMode$.MODULE$.allModes().foreach(mode -> {
Double cost = 0.0;
for (String costType : costTypes) {
Expand Down
Loading

0 comments on commit 067a827

Please sign in to comment.