Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add misc summary stats #1085

Merged
merged 32 commits into from
Dec 31, 2018
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
17478be
add misc summary stats
rajnikantsh Dec 26, 2018
f424bf7
add null check and change return syntax
rajnikantsh Dec 27, 2018
2b592f6
refactoring
wrashid Dec 27, 2018
28e1ef0
bug fix: wrong field used
wrashid Dec 27, 2018
264fd05
refactor: reuse code
wrashid Dec 27, 2018
89a3f33
add totalHoursOfVehicleTrafficDelay in summary stats.
rajnikantsh Dec 27, 2018
9512003
add summary stats for averagePTWaitingTime
rajnikantsh Dec 27, 2018
1e47ea0
add bus crowding in summary stats
rajnikantsh Dec 27, 2018
a6a41e0
reset bus crowding
rajnikantsh Dec 27, 2018
868fca1
add averageTripExpenditure in summary stats
rajnikantsh Dec 27, 2018
1be997b
fixed cost aggregation
Dec 28, 2018
f50c8ef
fixed PTCrowding (bus)
Dec 28, 2018
25b3fd9
renamed to totalNetCost
Dec 28, 2018
624d95c
fixed warnings
Dec 28, 2018
73d3392
reset ptWaiting against personId
Dec 28, 2018
360b39e
fixed average and update labels
Dec 28, 2018
1ae9793
hoursTraveled should be renamed to travelDurationInSec, as this is no…
Dec 28, 2018
2725231
remove / 3600 for busCrowding
Dec 28, 2018
7a160a3
fixed hard coding of modes
Dec 28, 2018
476eb75
fixed hard coding of modes
Dec 28, 2018
65e326d
rename _person
Dec 28, 2018
9cc0301
fixed warnings and format
Dec 28, 2018
28c7be6
create summary stats for average vehicle delay for motorized leg. (#1…
rajnikantsh Dec 28, 2018
1050166
fixed numOfTimesBusTaken in busCrowding
Dec 29, 2018
76e0ef4
changed buses list to set
Dec 29, 2018
c167545
fixed averageVehicleDelay
Dec 30, 2018
7306232
fixed delay stat variable name
Dec 30, 2018
f860b7e
Merge branch 'master' into rajnikantsh/#1084-add-misc-summarystats-4ci
Dec 30, 2018
67b9669
fixed delay stats calculation
Dec 30, 2018
e851285
fix n/0 issue
Dec 30, 2018
b0bc67e
fix totalVehicles for averageDelays
Dec 31, 2018
118bab9
Merge branch 'master' into rajnikantsh/#1084-add-misc-summarystats-4ci
Dec 31, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
38 changes: 24 additions & 14 deletions src/main/java/beam/analysis/summary/PersonCostAnalysis.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,55 @@
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 String[] costTypes = {"Cost", "Subsidy", "Toll"};
private Map<String,Double> personCostByCostType = new HashMap<>();
private String[] costTypes = {"Cost","Subsidy","Toll"};
private int numberOfTrips = 0;
private double totalNetCost = 0.0;

@Override
public void processStats(Event event) {
if (event instanceof PersonCostEvent || event.getEventType().equalsIgnoreCase(PersonCostEvent.EVENT_TYPE)) {
if (event instanceof PersonCostEvent || event.getEventType().equalsIgnoreCase(PersonCostEvent.EVENT_TYPE)){
Map<String, String> attributes = event.getAttributes();
String mode = attributes.get(PersonCostEvent.ATTRIBUTE_MODE);
Double cost = 0.0;
for (String costType : costTypes) {
switch (costType) {
case "Cost":
cost = Double.parseDouble(attributes.get(PersonCostEvent.ATTRIBUTE_NET_COST));
break;
case "Subsidy":
cost = Double.parseDouble(attributes.get(PersonCostEvent.ATTRIBUTE_SUBSIDY));
break;
case "Toll":
cost = Double.parseDouble(attributes.get(PersonCostEvent.ATTRIBUTE_TOLL_COST));
break;
for(String costType : costTypes){
switch (costType) {
case "Cost":
cost = Double.parseDouble(attributes.get(PersonCostEvent.ATTRIBUTE_NET_COST));
totalNetCost += cost;
break;
case "Subsidy":
cost = Double.parseDouble(attributes.get(PersonCostEvent.ATTRIBUTE_SUBSIDY));
break;
case "Toll":
cost = Double.parseDouble(attributes.get(PersonCostEvent.ATTRIBUTE_TOLL_COST));
break;
}
String statType = String.format("total%s_%s", costType, mode);
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