Skip to content

Commit

Permalink
Bl/#837 output data documentation 4ci (#923)
Browse files Browse the repository at this point in the history
* new class to describe the fields in any output data file generated

* new interface to define a stub to get output data descriptions for each class tht generates an output file

* output data descriptors implemented for ModeChosenAnalysis

* Merge branch 'master' into bl/#837-output-data-documentation-4ci

# Conflicts:
#	src/main/java/beam/analysis/plots/ModeChosenAnalysis.java

* output data descriptors implemented for ModeChosenAnalysis

* new class to generate the data descriptions table and write it to an output file

* data descriptions added for RealizedModeChoiceAnalysis and RideHailRevenueAnalysis

* data descriptions added for PersonTravelTimeAnalysis

* data descriptions added for FuelUsageAnalysis

* data descriptions added for ExpectedMaxUtilityHeatMap

* data descriptions added for physsim stats

* data descriptions added for RideHailWaitingAnalysis

* data descriptions added for RideHailWaitingAnalysis and Graph Surge Pricing

* partial commit

* data descriptions added for DeadHeadingAnalysis , summary stats , score stats and stop watch

* data descriptions added for summarystats

* data descriptions added for events

* data descriptions added for
    rideHailTripDistanceOutputs,
    tripDurationOutputs,
    biasErrorGraphDataOutputs,
    biasNormalizedErrorGraphDataOutputs

* Merge branch 'master' into bl/#837-output-data-documentation-4ci

# Conflicts:
#	src/main/scala/beam/sim/config/BeamConfig.scala

* use injected transport network while creating BeamMobsim instance in Output data description generator class
  • Loading branch information
bhavyalatha26 authored and colinsheppard committed Nov 13, 2018
1 parent 3b4f357 commit 118952f
Show file tree
Hide file tree
Showing 20 changed files with 783 additions and 92 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package beam.analysis.physsim;

import beam.analysis.plots.GraphsStatsAgentSimEventsListener;
import beam.sim.OutputDataDescription;
import beam.sim.config.BeamConfig;
import beam.utils.OutputDataDescriptor;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
Expand All @@ -20,17 +23,16 @@
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
* @author Bhavya Latha Bandaru.
* This class computes the distribution of free flow speed (in both m/s and %) over the network.
*/
public class PhyssimCalcLinkSpeedDistributionStats {
public class PhyssimCalcLinkSpeedDistributionStats implements OutputDataDescriptor {

private static int noOfBins = 24;
private BeamConfig beamConfig;
Expand Down Expand Up @@ -72,8 +74,8 @@ public void notifyIterationEnds(int iteration,TravelTimeCalculator travelTimeCal
//If not running in test mode , write output to a csv file
if (isNotTestMode()) {
//write data outputs to CSV
this.writeCSV(speedDataMatrix,outputDirectoryHierarchy.getIterationFilename(iteration, outputAsSpeedUnitFileName+".csv"),"Free Speed Distribution(m/s)");
this.writeCSV(processedSpeedDistributionAsPercentageData,outputDirectoryHierarchy.getIterationFilename(iteration, outputAsPercentageFileName+".csv"),"Free Speed Distribution(%)");
this.writeCSV(speedDataMatrix,outputDirectoryHierarchy.getIterationFilename(iteration, outputAsSpeedUnitFileName+".csv"),"freeSpeedInMetersPerSecond");
this.writeCSV(processedSpeedDistributionAsPercentageData,outputDirectoryHierarchy.getIterationFilename(iteration, outputAsPercentageFileName+".csv"),"linkEfficiencyInPercentage");
}
//generate the required charts - frequency over speed (as m/s)
generateSpeedDistributionBarChart(dataSetForSpeed,iteration);
Expand Down Expand Up @@ -107,13 +109,13 @@ private CategoryDataset generateLinkEfficienciesDataSet(Map<Double, Integer> gen
private void writeCSV(double[][] dataMatrix,String outputFilePath,String heading) {
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(outputFilePath));
String completeHeading = heading + ",x-coordinate,y-coordinate\n";
String completeHeading = heading + ",numberOfLinks\n";
bw.write(completeHeading);
double[] data = dataMatrix[0];
IntStream.range(0,data.length)
.forEach( i -> {
try {
bw.write( i + "," + i + "," + data[i] + "\n");
bw.write(i + "," + data[i] + "\n");
} catch (IOException e) {
e.printStackTrace();
}
Expand All @@ -133,7 +135,7 @@ private void writeCSV(double[][] dataMatrix,String outputFilePath,String heading
private void writeCSV(Map<Double, Integer> dataMap,String outputFilePath,String heading) {
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(outputFilePath));
String completeHeading = heading + ",x-coordinate,y-coordinate\n";
String completeHeading = heading + ",linkEfficiencyRounded,numberOfLinks\n";
bw.write(completeHeading);
dataMap.forEach((k,v) -> {
try {
Expand Down Expand Up @@ -172,24 +174,14 @@ public Map<Integer, Integer> generateInputDataForFreeFlowSpeedGraph(int binsCoun
return freeFlowSpeedFrequencies;
}

public Stream<Double> getDistinctFreeSpeeds(int binsCount,Network network) {
return Stream.iterate(0, x -> x)
.limit(binsCount)
.flatMap(bin -> network.getLinks().values()
.stream()
.map(link -> link.getFreespeed(bin * 3600)))
.distinct();
}

/**
* Generates input data used to generate frequencies of link efficiencies
* @return input generated data as map ( speed in m/s -> frequency )
*/
private Map<Double, Integer> generateInputDataForLinkEfficiencies(TravelTimeCalculator travelTimeCalculator) {
int binSize = 3600;
TravelTime travelTime = travelTimeCalculator.getLinkTravelTimes();
Map<Integer, Integer> frequencyOfEfficiencies = new HashMap<>();
Map<Double, Integer> frequencyOfEfficiencies1 = new HashMap<>();
Map<Double, Integer> frequencyOfEfficiencies = new HashMap<>();
//for each bin
for (int idx = 0; idx < noOfBins; idx++) {
//for each link
Expand All @@ -200,13 +192,11 @@ private Map<Double, Integer> generateInputDataForLinkEfficiencies(TravelTimeCalc
double averageSpeed = linkLength / averageTime;
//calculate the average speed of the link
double averageSpeedToFreeSpeedRatio = averageSpeed / freeSpeed;
Integer frequencyCount = frequencyOfEfficiencies.getOrDefault((int) Math.round(averageSpeedToFreeSpeedRatio*100),0);
Integer frequencyCount1 = frequencyOfEfficiencies1.getOrDefault(averageSpeedToFreeSpeedRatio*100,0);
frequencyOfEfficiencies.put((int) Math.round(averageSpeedToFreeSpeedRatio*100),frequencyCount+1);
frequencyOfEfficiencies1.put(averageSpeedToFreeSpeedRatio*100,frequencyCount1+1);
Integer frequencyCount1 = frequencyOfEfficiencies.getOrDefault(averageSpeedToFreeSpeedRatio*100,0);
frequencyOfEfficiencies.put(averageSpeedToFreeSpeedRatio*100,frequencyCount1+1);
}
}
return frequencyOfEfficiencies1;
return frequencyOfEfficiencies;
}

/**
Expand Down Expand Up @@ -286,4 +276,23 @@ private void generateSpeedDistributionAsPercentageChart(CategoryDataset dataSet,
}
}

/**
* Get description of fields written to the output files.
*
* @return list of data description objects
*/
@Override
public List<OutputDataDescription> getOutputDataDescriptions() {
String freeSpeedDistOutputFilePath = GraphsStatsAgentSimEventsListener.CONTROLLER_IO.getIterationFilename(0,outputAsSpeedUnitFileName + ".csv");
String freeSpeedDistAsPercetnageOutputFilePath = GraphsStatsAgentSimEventsListener.CONTROLLER_IO.getIterationFilename(0,outputAsSpeedUnitFileName + ".csv");
String outputDirPath = GraphsStatsAgentSimEventsListener.CONTROLLER_IO.getOutputPath();
String freeSpeedDistRelativePath = freeSpeedDistOutputFilePath.replace(outputDirPath, "");
String freeSpeedDistAsPercetnageRelativePath = freeSpeedDistAsPercetnageOutputFilePath.replace(outputDirPath, "");
List<OutputDataDescription> list = new ArrayList<>();
list.add(new OutputDataDescription(this.getClass().getSimpleName(), freeSpeedDistRelativePath, "freeSpeedInMetersPerSecond", "The possible full speed at which a vehicle can drive through the given link (in m/s)"));
list.add(new OutputDataDescription(this.getClass().getSimpleName(), freeSpeedDistRelativePath, "numberOfLinks", "Total number of links in the network that allow vehicles to travel with speeds up to the given free speed"));
list.add(new OutputDataDescription(this.getClass().getSimpleName(), freeSpeedDistAsPercetnageRelativePath, "linkEfficiencyInPercentage", "Average speed efficiency recorded by the the given network link in a day"));
list.add(new OutputDataDescription(this.getClass().getSimpleName(), freeSpeedDistAsPercetnageRelativePath, "numberOfLinks", "Total number of links having the corresponding link efficiency"));
return list;
}
}
26 changes: 22 additions & 4 deletions src/main/java/beam/analysis/physsim/PhyssimCalcLinkSpeedStats.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package beam.analysis.physsim;

import beam.analysis.plots.GraphsStatsAgentSimEventsListener;
import beam.sim.OutputDataDescription;
import beam.sim.config.BeamConfig;
import beam.utils.OutputDataDescriptor;
import org.jfree.chart.*;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
Expand All @@ -25,7 +28,7 @@
* @author Bhavya Latha Bandaru.
* This class computes the percentage of average speed over free speed for the network within a day.
*/
public class PhyssimCalcLinkSpeedStats {
public class PhyssimCalcLinkSpeedStats implements OutputDataDescriptor {

private static final List<Color> colors = new ArrayList<>();
private static int noOfBins = 24;
Expand Down Expand Up @@ -74,7 +77,7 @@ public void notifyIterationEnds(int iteration, TravelTimeCalculator travelTimeCa
private void writeCSV(Map<Integer, Double> processedData,String path) {
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(path));
String heading = "Bin,x-coordinate,y-coordinate\n";
String heading = "Bin,AverageLinkSpeed\n";
bw.write(heading);
for (int i = 0; i < processedData.size(); i++) {
String line = String.valueOf(i) + "," + String.valueOf(i) + "," + String.valueOf(processedData.get(i)) + "\n";
Expand Down Expand Up @@ -139,8 +142,8 @@ private double[][] buildDataSetFromProcessedData(Map<Integer, Double> processedD
private void generateAverageLinkSpeedGraph(CategoryDataset dataSet, int iterationNumber) {
// Settings legend and title for the plot
String plotTitle = "Average Link speed over a day";
String x_axis = "Hour";
String y_axis = "Average Link Speed %";
String x_axis = "Bin";
String y_axis = "AverageLinkSpeed";
int width = 800;
int height = 600;

Expand Down Expand Up @@ -213,4 +216,19 @@ public int getNumberOfBins() {
return noOfBins;
}

/**
* Get description of fields written to the output files.
*
* @return list of data description objects
*/
@Override
public List<OutputDataDescription> getOutputDataDescriptions() {
String freeSpeedDistOutputFilePath = GraphsStatsAgentSimEventsListener.CONTROLLER_IO.getIterationFilename(0,outputFileName + ".csv");
String outputDirPath = GraphsStatsAgentSimEventsListener.CONTROLLER_IO.getOutputPath();
String freeSpeedDistRelativePath = freeSpeedDistOutputFilePath.replace(outputDirPath, "");
List<OutputDataDescription> list = new ArrayList<>();
list.add(new OutputDataDescription(this.getClass().getSimpleName(), freeSpeedDistRelativePath, "Bin", "A given time slot within a day"));
list.add(new OutputDataDescription(this.getClass().getSimpleName(), freeSpeedDistRelativePath, "AverageLinkSpeed", "The average speed at which a vehicle can travel across the network during the given time bin"));
return list;
}
}
25 changes: 23 additions & 2 deletions src/main/java/beam/analysis/plots/DeadHeadingAnalysis.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import beam.analysis.plots.passengerpertrip.GenericPassengerPerTrip;
import beam.analysis.plots.passengerpertrip.IGraphPassengerPerTrip;
import beam.analysis.plots.passengerpertrip.TncPassengerPerTrip;
import beam.sim.OutputDataDescription;
import beam.utils.OutputDataDescriptor;
import com.google.common.base.CaseFormat;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.CategoryPlot;
Expand All @@ -21,7 +23,7 @@
import java.io.IOException;
import java.util.*;

public class DeadHeadingAnalysis implements GraphAnalysis {
public class DeadHeadingAnalysis implements GraphAnalysis, OutputDataDescriptor {
private static final Integer TNC_MAX_PASSENGERS = 6;
private static final Integer CAR_MAX_PASSENGERS = 4;
private static final int METERS_IN_KM = 1000;
Expand All @@ -30,6 +32,7 @@ public class DeadHeadingAnalysis implements GraphAnalysis {
private static final String deadHeadingXAxisTitle = "Hour";
private static final String deadHeadingYAxisTitle = "# trips";
private static final String fileNameBase = "rideHail";
private static final String dataFileBaseName = "rideHailStats";
private static final int DEFAULT_OCCURRENCE = 1;
private static Map<String, Map<Integer, Map<Integer, Integer>>> deadHeadingsMap = new HashMap<>();
private static Map<Integer, Map<Integer, Double>> deadHeadingsTnc0Map = new HashMap<>();
Expand Down Expand Up @@ -721,7 +724,7 @@ public int getDeadHeadingTnc0HourDataCount(int hourIndex) {

private void writeRideHailStatsCSV(IterationEndsEvent event) {

String csvFileName = event.getServices().getControlerIO().getOutputFilename("rideHailStats.csv");
String csvFileName = event.getServices().getControlerIO().getOutputFilename(dataFileBaseName + ".csv");
try (BufferedWriter out = new BufferedWriter(new FileWriter(new File(csvFileName)))) {

String heading = "Iteration,rideHailRevenue,averageRideHailWaitingTimeInSeconds,totalRideHailWaitingTimeInSeconds,passengerVKT,repositioningVKT,deadHeadingVKT,averageSurgePriceLevel,maxSurgePriceLevel,reservationCount";
Expand Down Expand Up @@ -807,4 +810,22 @@ private String getEventMode(Map<String, String> attributes) {
return attributes.get(PathTraversalEvent.ATTRIBUTE_MODE);
}

@Override
public List<OutputDataDescription> getOutputDataDescriptions() {
String outputFilePath = GraphsStatsAgentSimEventsListener.CONTROLLER_IO.getOutputFilename(dataFileBaseName + ".csv");
String outputDirPath = GraphsStatsAgentSimEventsListener.CONTROLLER_IO.getOutputPath();
String relativePath = outputFilePath.replace(outputDirPath, "");
List<OutputDataDescription> list = new ArrayList<>();
list.add(new OutputDataDescription(this.getClass().getSimpleName(), relativePath, "iterations", "iteration number"));
list.add(new OutputDataDescription(this.getClass().getSimpleName(), relativePath, "rideHailRevenue", "Revenue generated from ride hail"));
list.add(new OutputDataDescription(this.getClass().getSimpleName(), relativePath, "averageRideHailWaitingTimeInSeconds", "The average time spent by a passenger on waiting for hailing a ride"));
list.add(new OutputDataDescription(this.getClass().getSimpleName(), relativePath, "totalRideHailWaitingTimeInSeconds", "The total time spent by a passenger on waiting for hailing a ride"));
list.add(new OutputDataDescription(this.getClass().getSimpleName(), relativePath, "passengerVKT", "Kilometers travelled by the vehicle with a passenger"));
list.add(new OutputDataDescription(this.getClass().getSimpleName(), relativePath, "repositioningVKT", "Kilometers travelled by the vehicle to reposition to fleet"));
list.add(new OutputDataDescription(this.getClass().getSimpleName(), relativePath, "deadHeadingVKT", "Kilometers travelled by an empty vehicle towards the passenger"));
list.add(new OutputDataDescription(this.getClass().getSimpleName(), relativePath, "averageSurgePriceLevel", "The average value of surged price levels of ride hail"));
list.add(new OutputDataDescription(this.getClass().getSimpleName(), relativePath, "maxSurgePriceLevel", "The maximum value of surged price levels of ride hail"));
list.add(new OutputDataDescription(this.getClass().getSimpleName(), relativePath, "reservationCount", "Count of the number of passenger reservations made for the ride hail"));
return list;
}
}
Loading

0 comments on commit 118952f

Please sign in to comment.