org.opentripplanner.graph_builder.GraphStats Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of otp Show documentation
Show all versions of otp Show documentation
The OpenTripPlanner multimodal journey planning system
package org.opentripplanner.graph_builder;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.csvreader.CsvWriter;
import com.google.common.collect.Multiset;
import com.google.common.collect.TreeMultiset;
import org.geotools.referencing.GeodeticCalculator;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.linearref.LinearLocation;
import org.locationtech.jts.linearref.LocationIndexedLine;
import org.opentripplanner.model.Trip;
import org.opentripplanner.model.TripPattern;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.routing.graph.SerializedGraphObject;
import org.opentripplanner.routing.graph.Vertex;
import org.opentripplanner.routing.vertextype.StreetVertex;
import org.opentripplanner.routing.vertextype.TransitStopVertex;
import org.opentripplanner.util.OtpAppException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.geom.Point2D;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class GraphStats {
private static final Logger LOG = LoggerFactory.getLogger(GraphStats.class);
@Parameter(names = { "-v", "--verbose" }, description = "Verbose output")
private boolean verbose = false;
@Parameter(names = { "-d", "--debug"}, description = "Debug mode")
private boolean debug = false;
@Parameter(names = { "-h", "--help"}, description = "Print this help message and exit", help = true)
private boolean help;
@Parameter(names = { "-g", "--graph"}, description = "path to the graph file", required = true)
private String graphPath;
@Parameter(names = { "-o", "--out"}, description = "output file")
private String outPath;
private CommandEndpoints commandEndpoints = new CommandEndpoints();
private CommandPatternStats commandPatternStats = new CommandPatternStats();
private JCommander jc;
private Graph graph;
private CsvWriter writer;
public static void main(String[] args) {
GraphStats graphStats = new GraphStats(args);
try {
graphStats.run();
}
catch (OtpAppException ignore) {
// The error is handled at a lover level
}
}
private GraphStats(String[] args) {
jc = new JCommander(this);
jc.addCommand(commandEndpoints);
jc.addCommand(commandPatternStats);
try {
jc.parse(args);
} catch (Exception e) {
System.out.println(e.getMessage());
jc.usage();
System.exit(1);
}
if (help || jc.getParsedCommand() == null) {
jc.usage();
System.exit(0);
}
}
private void run() {
/* open input graph (same for all commands) */
File graphFile = new File(graphPath);
graph = SerializedGraphObject.load(graphFile);
/* open output stream (same for all commands) */
if (outPath != null) {
try {
writer = new CsvWriter(outPath, ',', Charset.forName("UTF8"));
} catch (Exception e) {
LOG.error("Exception while opening output file " + outPath);
return;
}
} else {
writer = new CsvWriter(System.out, ',', Charset.forName("UTF8"));
}
LOG.info("done loading graph.");
String command = jc.getParsedCommand();
if (command.equals("endpoints")) {
commandEndpoints.run();
} else if (command.equals("patternstats")) {
commandPatternStats.run();
}
writer.close();
}
@Parameters(commandNames = "endpoints", commandDescription = "Generate random endpoints for performance testing")
class CommandEndpoints {
@Parameter(names = { "-r", "--radius"}, description = "perturbation radius in meters")
private double radius = 100;
@Parameter(names = { "-n", "--number"}, description = "number of endpoints to generate")
private int n = 20;
@Parameter(names = { "-s", "--stops"}, description = "choose endpoints near stops not street vertices")
private boolean useStops = false;
@Parameter(names = { "-rs", "--seed"}, description = "random seed, allows reproducible results")
private Long seed = null;
// go along road then random
public void run() {
LOG.info(String.format("Producing %d random endpoints within radius %2.2fm around %s.",
n, radius, useStops ? "stops" : "streets"));
List vertices = new ArrayList();
GeodeticCalculator gc = new GeodeticCalculator();
Class> klasse = useStops ? TransitStopVertex.class : StreetVertex.class;
for (Vertex v : graph.getVertices())
if (klasse.isInstance(v))
vertices.add(v);
Random random = new Random();
if (seed != null)
random.setSeed(seed);
Collections.shuffle(vertices, random);
vertices = vertices.subList(0, n);
try {
writer.writeRecord(new String[]{"n", "name", "lon", "lat"});
int i = 0;
for (Vertex v : vertices) {
Coordinate c;
if (v instanceof StreetVertex) {
LineString ls = ((StreetVertex) v).getOutgoing().iterator().next().getGeometry();
int numPoints = ls.getNumPoints();
LocationIndexedLine lil = new LocationIndexedLine(ls);
int seg = random.nextInt(numPoints);
double frac = random.nextDouble();
LinearLocation ll = new LinearLocation(seg, frac);
c = lil.extractPoint(ll);
} else {
c = v.getCoordinate();
}
// perturb
double distance = random.nextDouble() * radius;
double azimuth = random.nextDouble() * 360 - 180;
// double x = c.x + r * Math.cos(theta);
// double y = c.y + r * Math.sin(theta);
gc.setStartingGeographicPoint(c.x, c.y);
gc.setDirection(azimuth, distance);
Point2D dest = gc.getDestinationGeographicPoint();
String name = v.getName();
String[] entries = new String[]{
Integer.toString(i),
name,
Double.toString(dest.getX()),
Double.toString(dest.getY())
};
writer.writeRecord(entries);
i += 1;
}
} catch (IOException ioe) {
LOG.error("Excpetion while writing CSV: {}", ioe.getMessage());
}
LOG.info("done.");
}
}
@Parameters(commandNames = "patternstats", commandDescription = "trip pattern stats")
class CommandPatternStats {
public void run() {
LOG.info("counting number of trips per pattern...");
try {
writer.writeRecord( new String[] {
"nTripsInPattern", "frequency",
"cumulativePatterns", "empiricalDistPatterns",
"cumulativeTrips", "empiricalDistTrips"
} );
Collection patterns = graph.tripPatternForId.values();
Multiset counts = TreeMultiset.create();
int nPatterns = patterns.size();
LOG.info("total number of patterns is: {}", nPatterns);
int nTrips = 0;
for (TripPattern ttp : patterns) {
List trips = ttp.getTrips();
counts.add(trips.size());
nTrips += trips.size();
}
LOG.info("total number of trips is: {}", nTrips);
LOG.info("average number of trips per pattern is: {}", nTrips/nPatterns);
int cPatterns = 0;
int cTrips = 0;
for (Multiset.Entry count : counts.entrySet()) {
cPatterns += count.getCount();
cTrips += count.getCount() * count.getElement();
writer.writeRecord( new String[] {
count.getElement().toString(),
Integer.toString(count.getCount()),
Integer.toString(cPatterns),
Double.toString(cPatterns / (double) nPatterns),
Integer.toString(cTrips),
Double.toString(cTrips / (double) nTrips)
} );
}
} catch (IOException e) {
LOG.error("Exception writing CSV: {}", e.getMessage());
return;
}
LOG.info("done.");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy