Ejemplo n.º 1
0
    def from_gtfs(feed, route_id, service_id, shape_id=None):
        """
        A way to build a trip from GTFS data.
        Args:
            feed: the GTFS feed that contains the route
            route_id (int): the route_id for the route
            service_id (int): the service_id for the trip
            shape_id (int): the shape_id for the route
        Returns:
            dpd.driving.Trip: a Trip
        """
        trips = feed.trips[(feed.trips["route_id"] == route_id) &
                           (feed.trips["service_id"] == service_id)]["trip_id"]
        if not shape_id:
            shape_id = feed.trips[feed.trips["trip_id"] ==
                                  trips.iloc[0]].shape_id.iloc[0]
        line = feed.build_geometry_by_shape([shape_id])[shape_id]
        aea_line = epsg4326_to_aea(line)

        @lru_cache(
            maxsize=128
        )  # adds a little complexity, but reduces runtime by half :)
        def stop_id_to_distance_cached(stop_id):
            return trip._stop_id_to_distance(feed, aea_line, stop_id)

        trip = Trip()
        for trip_id in trips:
            d = feed.stop_times[feed.stop_times["trip_id"] == trip_id].copy()
            d["arrival_time_object"] = d.arrival_time.map(
                timestring_to_timeobject)
            d["departure_time_object"] = d.departure_time.map(
                timestring_to_timeobject)
            d["distance"] = d.stop_id.map(stop_id_to_distance_cached)
        for index, stop in d.iterrows():
            trip.add_stop(name="",
                          geometry=Point(
                              feed.stops[feed.stops.stop_id ==
                                         stop["stop_id"]]["stop_lon"],
                              feed.stops[feed.stops.stop_id ==
                                         stop["stop_id"]]["stop_lat"]),
                          distance=stop["distance"],
                          arrival_time=stop["arrival_time_object"],
                          departure_time=stop["departure_time_object"])
        return trip
Ejemplo n.º 2
0
def plot_schedule(feed, route_id, service_id, shape_id=None):
    trips = feed.trips[
        (feed.trips["route_id"] == route_id) & (feed.trips["service_id"] == service_id)
    ]["trip_id"]
    if not shape_id:
        shape_id = feed.trips[feed.trips["trip_id"] == trips.iloc[0]].shape_id.iloc[0]
    line = feed.build_geometry_by_shape([shape_id])[shape_id]
    aea_line = epsg4326_to_aea(line)

    @lru_cache(maxsize=128)  # adds a little complexity, but reduces runtime by half :)
    def stop_id_to_distance_cached(stop_id):
        return _stop_id_to_distance(feed, aea_line, stop_id)

    for trip_id in trips:
        d = feed.stop_times[feed.stop_times["trip_id"] == trip_id].copy()
        d["arrival_time_object"] = d.arrival_time.map(timestring_to_timeobject)
        d["departure_time_object"] = d.departure_time.map(timestring_to_timeobject)
        d["distance"] = d.stop_id.map(stop_id_to_distance_cached)
        plt.plot(d.arrival_time_object, d.distance / 1000)
    plt.xlabel("Time of Day")
    plt.ylabel("Distance on Route")
    plt.show()
Ejemplo n.º 3
0
    def __init__(
        self,
        way,
        stops=[],
        tolerance=None,
        max_cant=0.1524,
        max_cant_deficiency=0.075,
        gague=1.435,
    ):
        """
        Args:
            way (shapely.geometry.LineString): a LineString that contains the route the vehicle follows in EPSG:4326
            stops ([{"geo": shapely.geometry.Point, "name": str}]): a list of "stops" that have a name and a geometry
            tolerance (int): the minimum distance (in meters) for which to keep neighboring stops so they do not create unrealistic curves
            max_cant: (float): the maximum allowable cant (in meters)
            max_cant_deficiency (float): the maximum allowable cant deficiency (in meters)
            gague (float): the track gague (in meters)

        Returns:
            dpd.driving.Route: a route table
        """
        aea_way = epsg4326_to_aea(way)
        index = list(map(str, zip(way.xy[0], way.xy[1])))
        geometry = list(map(Point, zip(aea_way.xy[0], aea_way.xy[1])))
        super().__init__(geometry, columns=["geometry"], index=index)
        self.crs = "North America Albers Equal Area Conic"
        self["stop_name"] = ""
        for stop in stops:
            self.at[stop["geo"], "stop_name"] = stop["name"]
        self["after_geometry"] = self["geometry"].shift(-1)
        self["distance_to_next_point"] = self.apply(
            lambda row: None if not row["after_geometry"] else LineString(
                [row["geometry"], row["after_geometry"]]).length,
            axis=1,
        )
        if (
                tolerance
        ):  # not perfect (e.g. it is possible we will compeltely remove a segment where there are many close points and we really wanted to keep one or two)
            self.drop(
                self[(self["distance_to_next_point"] < tolerance)
                     & (self["stop_name"] == "")].index,
                inplace=True,
            )
            self["after_geometry"] = self["geometry"].shift(-1)
            self["distance_to_next_point"] = self.apply(
                lambda row: None if not row["after_geometry"] else LineString(
                    [row["geometry"], row["after_geometry"]]).length,
                axis=1,
            )
        self["total_distance_to_this_point"] = (
            self["distance_to_next_point"].shift(1).cumsum().fillna(0))
        self["before_geometry"] = self["geometry"].shift(1)
        self["radius_of_curvature"] = self.apply(
            lambda row: 5000 if row["before_geometry"] is None or row[
                "after_geometry"] is None else radius_of_curvature(
                    (row["before_geometry"].x, row["before_geometry"].y),
                    (row["geometry"].x, row["geometry"].y),
                    (row["after_geometry"].x, row["after_geometry"].y),
                ),
            axis=1,
        )
        self["speed_limit"] = self["radius_of_curvature"].apply(
            lambda radius_of_curvature: np.sqrt(9.8 * (
                max_cant + max_cant_deficiency) * radius_of_curvature / gague))
        self.max_cant: float = max_cant
        self.max_cant_deficiency: float = max_cant_deficiency
        self.gague: float = gague
Ejemplo n.º 4
0
 def _stop_id_to_distance(feed, aea_line, stop_id):
     stop = feed.stops[feed.stops.stop_id == stop_id]
     stop_point = Point(stop.stop_lon, stop.stop_lat)
     stop_point_aea = epsg4326_to_aea(stop_point)
     distance = aea_line.project(stop_point_aea)
     return distance
Ejemplo n.º 5
0
 def calculate_aea_geometry(self):
     """
     Calculate an aea_geometry column.
     """
     self["aea_geometry"] = self.geometry.map(
         lambda geometry: epsg4326_to_aea(geometry))
Ejemplo n.º 6
0
 def test_epsg4326_to_aea(self):
     point = Point(-118.481389, 34.021944)
     aea_point = epsg4326_to_aea(point)
     self.assertEqual(aea_point.x, -1955052.147737653)
     self.assertEqual(aea_point.y, -468997.4237058063)