Exemple #1
0
    def add_stops_to_feed(self, feed, data):
        stops = data.get_stops()
        stops_by_name = {}

        for internal_stop_id, a_stop in stops['regular'].items():
            if a_stop.name not in stops_by_name:
                stops_by_name[a_stop.name] = []
            stops_by_name[a_stop.name].append(a_stop)

        for a_stop_name in stops_by_name:
            stop_areas = []

            for a_stop_point in sorted(stops_by_name[a_stop_name],
                                       key=get_stop_id):
                gtfs_stop_point = create_stop_point(a_stop_point, feed)
                stop_point_has_parent_location = False
                for a_stop_area in stop_areas:
                    distance_to_parent_station = Helper.get_crow_fly_distance(
                        (a_stop_area.stop_lat, a_stop_area.stop_lon),
                        (a_stop_point.lat, a_stop_point.lon))
                    if distance_to_parent_station < 500:
                        gtfs_stop_point.parent_station = a_stop_area.stop_id
                        stop_point_has_parent_location = True
                        break
                if not stop_point_has_parent_location:
                    new_sa = create_stop_area(a_stop_point, feed)
                    gtfs_stop_point.parent_station = new_sa.stop_id
                    stop_areas.append(new_sa)
    def add_stops_to_feed(self, feed, data):
        stops = data.get_stops()
        stops_by_name = {}

        for internal_stop_id, a_stop in stops['regular'].items():
            if a_stop.name not in stops_by_name:
                stops_by_name[a_stop.name] = []
            stops_by_name[a_stop.name].append(a_stop)

        for a_stop_name in stops_by_name:
            stop_areas = []

            for a_stop_point in sorted(stops_by_name[a_stop_name], key=get_stop_id):
                gtfs_stop_point = create_stop_point(a_stop_point, feed)
                stop_point_has_parent_location = False
                for a_stop_area in stop_areas:
                    distance_to_parent_station = Helper.get_crow_fly_distance(
                        (a_stop_area.stop_lat, a_stop_area.stop_lon),
                        (a_stop_point.lat, a_stop_point.lon)
                    )
                    if distance_to_parent_station < 500:
                        gtfs_stop_point.parent_station = a_stop_area.stop_id
                        stop_point_has_parent_location = True
                        break
                if not stop_point_has_parent_location:
                    new_sa = create_stop_area(a_stop_point, feed)
                    gtfs_stop_point.parent_station = new_sa.stop_id
                    stop_areas.append(new_sa)
Exemple #3
0
    def _build_stop(self, stop, osm_type):
        """Helper function to build a Stop object

        Returns a initiated Stop object from raw data

        """

        if self._is_valid_stop_candidate(stop):

            # Make sure name is not empty
            if "name" not in stop.tags:
                stop.tags["name"] = "[{}]".format(self.stop_no_name)

            # Ways don't have a pair of coordinates and need to be calculated
            if osm_type == "way":
                (stop.lat, stop.lon) = Helper.get_center_of_nodes(
                    stop.get_nodes())

            # Move to Elements class, once attributes with defaults play well
            # with inheritance https://github.com/python-attrs/attrs/issues/38
            osm_url = "https://osm.org/" + str(
                osm_type) + "/" + str(stop.id)

            # Create and return Stop object
            stop = Stop(osm_id=stop.id, osm_type=osm_type, osm_url=osm_url,
                        tags=stop.tags, name=stop.tags['name'], lat=stop.lat,
                        lon=stop.lon)
            return stop

        else:
            logging.warning(
                "Warning: Potential stop is invalid and has been ignored.")
            logging.warning(
                " Check tagging: https://osm.org/%s/%s", osm_type, stop.id)
            return None
Exemple #4
0
    def _define_route_text_color(self, route):
        """
        Returns the route_text_color for the use in the GTFS feed.
        Can be easily overridden in any creator.
        """
        if route.route_text_color is None:
            # Auto calculate text color with high contrast
            route.route_text_color = Helper.calculate_color_of_contrast(
                route.route_color)

        return route.route_text_color[1:]
Exemple #5
0
    def _define_route_text_color(self, route):
        """
        Returns the route_text_color for the use in the GTFS feed.
        Can be easily overridden in any creator.
        """
        if route.route_text_color is None:
            # Auto calculate text color with high contrast
            route.route_text_color = Helper.calculate_color_of_contrast(
                route.route_color)

        return route.route_text_color[1:]
    def add_trips_to_feed(self, feed, data):
        self.service_weekday = feed.GetDefaultServicePeriod()
        self.service_weekday.SetStartDate(
            self.config['feed_info']['start_date'])
        self.service_weekday.SetEndDate(self.config['feed_info']['end_date'])
        self.service_weekday.SetWeekdayService(True)
        self.service_weekday.SetWeekendService(True)

        lines = data.routes
        for route_ref, line in sorted(lines.iteritems()):
            if not isinstance(line, Line):
                continue
            print("Generating schedule for line: " + route_ref)

            line_gtfs = feed.AddRoute(
                short_name=str(line.route_id),
                long_name=line.name,
                # we change the route_long_name with the 'from' and 'to' tags
                # of the last route as the route_master name tag contains
                # the line code (route_short_name)
                route_type="Bus",
                route_id=line.osm_id)
            line_gtfs.agency_id = feed.GetDefaultAgency().agency_id
            line_gtfs.route_desc = ""
            line_gtfs.route_color = "1779c2"
            line_gtfs.route_text_color = "ffffff"

            route_index = 0
            itineraries = line.get_itineraries()
            for a_route in itineraries:
                trip_gtfs = line_gtfs.AddTrip(feed)
                trip_gtfs.shape_id = self._add_shape_to_feed(
                    feed, a_route.osm_id, a_route)
                trip_gtfs.direction_id = route_index % 2
                route_index += 1

                if a_route.fr and a_route.to:
                    trip_gtfs.trip_headsign = a_route.to
                    line_gtfs.route_long_name = a_route.fr.decode(
                        'utf8') + " ↔ ".decode('utf8') + a_route.to.decode(
                            'utf8')

                DEFAULT_ROUTE_FREQUENCY = 30
                DEFAULT_TRAVEL_TIME = 120

                frequency = None
                if "frequency" in line.tags:
                    frequency = line.tags['frequency']
                try:
                    ROUTE_FREQUENCY = int(frequency)
                    if not ROUTE_FREQUENCY > 0:
                        print("frequency is invalid for route_master " +
                              str(line.osm_id))
                        ROUTE_FREQUENCY = DEFAULT_ROUTE_FREQUENCY
                except (ValueError, TypeError) as e:
                    print("frequency not a number for route_master " +
                          str(line.osm_id))
                    ROUTE_FREQUENCY = DEFAULT_ROUTE_FREQUENCY
                trip_gtfs.AddFrequency("05:00:00", "22:00:00",
                                       ROUTE_FREQUENCY * 60)

                if 'travel_time' in a_route.tags:
                    try:
                        TRAVEL_TIME = int(a_route.tags['travel_time'])
                        if not TRAVEL_TIME > 0:
                            print("travel_time is invalid for route " +
                                  str(a_route.osm_id))
                            TRAVEL_TIME = DEFAULT_TRAVEL_TIME
                    except (ValueError, TypeError) as e:
                        print("travel_time not a number for route " +
                              str(a_route.osm_id))
                        TRAVEL_TIME = DEFAULT_TRAVEL_TIME

                for index_stop, a_stop in enumerate(a_route.stops):
                    stop_id = a_stop.split('/')[-1]
                    departure_time = datetime(2008, 11, 22, 6, 0, 0)

                    if index_stop == 0:
                        trip_gtfs.AddStopTime(
                            feed.GetStop(str(stop_id)),
                            stop_time=departure_time.strftime("%H:%M:%S"))
                    elif index_stop == len(a_route.stops) - 1:
                        departure_time += timedelta(minutes=TRAVEL_TIME)
                        trip_gtfs.AddStopTime(
                            feed.GetStop(str(stop_id)),
                            stop_time=departure_time.strftime("%H:%M:%S"))
                    else:
                        trip_gtfs.AddStopTime(feed.GetStop(str(stop_id)))

                for secs, stop_time, is_timepoint in trip_gtfs.GetTimeInterpolatedStops(
                ):
                    if not is_timepoint:
                        stop_time.arrival_secs = secs
                        stop_time.departure_secs = secs
                        trip_gtfs.ReplaceStopTimeObject(stop_time)

                Helper.interpolate_stop_times(trip_gtfs)
Exemple #7
0
    def add_trips_by_day(self, feed, line, service, route, horarios, day):

        # check if we even have service
        if horarios is None or len(horarios) == 0:
            return

        if isinstance(route, Line):
            # recurse into "Ida" and "Volta" routes
            for sub_route in route.get_itineraries():
                sub_route.duration = route.duration
                self.add_trips_by_day(feed, line, service, sub_route, horarios, day)
            return

        # have at least two stops
        if len(route.stops) < 2:
            sys.stderr.write("Skipping Route, has no stops: " + str(route) + "\n")
            return

        # check if we have a match for the first stop
        key = self.match_first_stops(route, horarios.keys())

        if key is None:
            # Do not print debug output here, because already done in route.match_first_stops()
            return

        if route.route_id == DEBUG_ROUTE:
            print "\n\n\n" + str(route)
            print day + " - " + key

        # get shape id
        shape_id = str(route.route_id)
        try:
            feed.GetShape(shape_id)
        except KeyError:
            shape = transitfeed.Shape(shape_id)
            for point in route.shape:
                shape.AddPoint(lat=float(point["lat"]), lon=float(point["lon"]))
            feed.AddShapeObject(shape)

        if len(horarios) > 1 and route.line is None:
            sys.stderr.write(
                "Route should have a master: [" + route.route_id + "] " + str(
                    route.osm_url) + "\n")

        for time_group in horarios[key]:
            for time_point in time_group:
                # parse first departure time
                start_time = datetime.strptime(time_point[0], "%H:%M")
                start_time = str(start_time.time())

                # calculate last arrival time for GTFS
                start_sec = transitfeed.TimeToSecondsSinceMidnight(start_time)
                factor = 1
                if len(horarios) > 1 and route.line is None:
                    # since this route has only one instead of two trips, double the duration
                    factor = 2
                end_sec = start_sec + route.duration.seconds * factor
                end_time = transitfeed.FormatSecondsSinceMidnight(end_sec)

                # TODO handle options
                # opts = time_point[1]

                trip = line.AddTrip(feed, headsign=route.name, service_period=service)
                # add empty attributes to make navitia happy
                trip.block_id = ""
                trip.wheelchair_accessible = ""
                trip.bikes_allowed = ""
                trip.shape_id = shape_id
                trip.direction_id = ""
                if route.route_id == DEBUG_ROUTE:
                    print "ADD TRIP " + str(trip.trip_id) + ":"
                self.add_trip_stops(feed, trip, route, start_time, end_time)

                # interpolate times, because Navitia can not handle this itself
                Helper.interpolate_stop_times(trip)
    def add_trips_to_feed(self, feed, data):
        transport_hours = transporthours.main.Main()
        default_hours = transport_hours.tagsToGtfs(self._DEFAULT_SCHEDULE)

        default_service_period = self._init_service_period(
            feed, default_hours[0])
        feed.SetDefaultServicePeriod(default_service_period)
        default_hours_dict = self._group_hours_by_service_period(
            feed, default_hours)

        lines = data.routes

        default_agency = feed.GetDefaultAgency()

        for route_id, line in sorted(lines.iteritems()):
            if not isinstance(line, Line):
                continue
            logging.info("Generating schedule for line: %s", route_id)
            if 'network' in line.tags and line.tags['network']:
                try:
                    agency = feed.GetAgency(line.tags['network'])
                except KeyError:
                    agency = feed.AddAgency(line.tags['network'],
                                            default_agency.agency_url,
                                            default_agency.agency_timezone,
                                            agency_id=line.tags['network'])
                    logging.info("Added agency: %s", agency.agency_name)
                    if not agency.Validate():
                        logging.error("Agency data not valid for %s in line",
                                      line.tags['network'])
                if 'operator:website' in line.tags and line.tags[
                        'operator:website']:
                    agency.agency_url = line.tags['operator:website']
                    if not agency.Validate():
                        logging.error('Url is not valid for agency: %s',
                                      agency.agency_url)
            else:
                agency = default_agency

            line_gtfs = feed.AddRoute(short_name=str(line.route_id),
                                      long_name=line.name,
                                      route_type=line.route_type,
                                      route_id=line.osm_id)
            line_gtfs.agency_id = agency.agency_id
            line_gtfs.route_desc = ""
            line_gtfs.route_color = "1779c2"
            line_gtfs.route_text_color = "ffffff"

            route_index = 0
            itineraries = line.get_itineraries()

            line_hours_list = transport_hours.tagsToGtfs(line.tags)
            line_hours_dict = self._group_hours_by_service_period(
                feed, line_hours_list)

            for a_route in itineraries:
                itinerary_hours_list = transport_hours.tagsToGtfs(a_route.tags)

                if itinerary_hours_list:
                    itinerary_hours_dict = self._group_hours_by_service_period(
                        feed, itinerary_hours_list)
                elif line_hours_dict:
                    itinerary_hours_dict = line_hours_dict
                else:
                    itinerary_hours_dict = default_hours_dict
                    logging.warning("schedule is missing, using default")
                    logging.warning(
                        " Add opening_hours & interval tags in OSM - %s",
                        line.osm_url)

                for service_id, itinerary_hours in itinerary_hours_dict.items(
                ):
                    service_period = feed.GetServicePeriod(service_id)
                    trip_gtfs = line_gtfs.AddTrip(
                        feed, service_period=service_period)
                    trip_gtfs.shape_id = self._add_shape_to_feed(
                        feed, a_route.osm_id, a_route)
                    trip_gtfs.direction_id = route_index % 2
                    route_index += 1

                    if a_route.fr and a_route.to:
                        trip_gtfs.trip_headsign = a_route.to
                        if line_gtfs.route_short_name:
                            # The line.name in the OSM data (route_long_name in the GTFS)
                            # is in the following format:
                            # '{transport mode} {route_short_name if any} :
                            # {A terminus} ↔ {The other terminus}'
                            # But it is good practice to not repeat the route_short_name
                            # in the route_long_name,
                            # so we abridge the route_long_name here if needed
                            line_gtfs.route_long_name = a_route.fr + \
                                " ↔ ".decode('utf-8') + a_route.to

                    for itinerary_hour in itinerary_hours:
                        trip_gtfs.AddFrequency(itinerary_hour['start_time'],
                                               itinerary_hour['end_time'],
                                               itinerary_hour['headway'])

                    if 'duration' in a_route.tags:
                        try:
                            travel_time = int(a_route.tags['duration'])
                            if not travel_time > 0:
                                logging.warning(
                                    "trip duration %s is invalid - %s",
                                    travel_time, a_route.osm_url)
                                travel_time = self._DEFAULT_TRIP_DURATION
                        except (ValueError, TypeError) as e:
                            logging.warning(
                                "trip duration %s is not a number - %s",
                                a_route.tags['duration'], a_route.osm_url)
                            travel_time = self._DEFAULT_TRIP_DURATION
                    else:
                        travel_time = self._DEFAULT_TRIP_DURATION
                        logging.warning(
                            "trip duration is missing, using default (%s min)",
                            travel_time)
                        logging.warning(" Add a duration tag in OSM - %s",
                                        a_route.osm_url)

                    for index_stop, a_stop in enumerate(a_route.stops):
                        stop_id = a_stop
                        departure_time = datetime(2008, 11, 22, 6, 0, 0)

                        if index_stop == 0:
                            trip_gtfs.AddStopTime(
                                feed.GetStop(str(stop_id)),
                                stop_time=departure_time.strftime("%H:%M:%S"))
                        elif index_stop == len(a_route.stops) - 1:
                            departure_time += timedelta(minutes=travel_time)
                            trip_gtfs.AddStopTime(
                                feed.GetStop(str(stop_id)),
                                stop_time=departure_time.strftime("%H:%M:%S"))
                        else:
                            trip_gtfs.AddStopTime(feed.GetStop(str(stop_id)))

                    for secs, stop_time, is_timepoint in trip_gtfs.GetTimeInterpolatedStops(
                    ):
                        if not is_timepoint:
                            stop_time.arrival_secs = secs
                            stop_time.departure_secs = secs
                            trip_gtfs.ReplaceStopTimeObject(stop_time)

                    Helper.interpolate_stop_times(trip_gtfs)
Exemple #9
0
    def _find_best_name_for_unnamed_stop(self, stop):
        """Define name for stop without explicit name based on sourroundings

        """
        api = overpy.Overpass()

        result = api.query("""
        <osm-script>
          <query type="way">
            <around lat="%s" lon="%s" radius="50.0"/>
            <has-kv k="name" />
            <has-kv modv="not" k="highway" v="trunk"/>
            <has-kv modv="not" k="highway" v="primary"/>
            <has-kv modv="not" k="highway" v="secondary"/>
            <has-kv modv="not" k="amenity" v="bus_station"/>
          </query>
          <print order="quadtile"/>
          <query type="node">
            <around lat="%s" lon="%s" radius="50.0"/>
            <has-kv k="name"/>
            <has-kv modv="not" k="highway" v="bus_stop"/>
          </query>
          <print order="quadtile"/>
        </osm-script>
        """ % (stop.lat, stop.lon, stop.lat, stop.lon))

        candidates = []

        # get all node candidates
        for node in result.get_nodes():
            if 'name' in node.tags and node.tags["name"] is not None:
                candidates.append(node)

        # get way node candidates
        for way in result.get_ways():
            if 'name' in way.tags and way.tags["name"] is not None:
                candidates.append(way)

        # leave if no candidates
        if len(candidates) == 0:
            # give stop a different name, so we won't search again without
            # refreshing data
            stop.name = self.stop_no_name
            return

        # find closest candidate
        winner = None
        winner_distance = sys.maxint
        for candidate in candidates:
            if isinstance(candidate, overpy.Way):
                lat, lon = Helper.get_center_of_nodes(
                    candidate.get_nodes(resolve_missing=True))
                distance = util.ApproximateDistance(lat, lon, stop.lat,
                                                    stop.lon)
            else:
                distance = util.ApproximateDistance(candidate.lat,
                                                    candidate.lon, stop.lat,
                                                    stop.lon)
            if distance < winner_distance:
                winner = candidate
                winner_distance = distance

        # take name from winner
        stop.name = winner.tags["name"]
Exemple #10
0
    def _build_station(self, stop_area, osm_type):
        """Helper function to build Station objects from stop_areas

        The function creates a Station object for the stop_area
        flagged as location_type = 1. This means station, that can
        group stops.

        The members of this relation add this station their parent.

        Returns a initiated Station object from raw data

        """
        # Check relation to be a station or used differently
        if 'route' in stop_area.tags:
            return None
        else:
            # Check tagging whether this is a stop area.
            if 'public_transport' not in stop_area.tags:
                logging.warning(
                    "Potential station has no public_transport tag.")
                logging.warning(" Please fix on OSM: https://osm.org/%s/%s",
                                osm_type, stop_area.id)
                return None
            elif stop_area.tags['public_transport'] != 'stop_area':
                logging.warning(
                    "Warning: Potential station is not tagged as stop_area.")
                logging.warning(" Please fix on OSM: https://osm.org/%s/%s",
                                osm_type, stop_area.id)
                return None

        # Analzyse member objects (stops) of this stop area
        members = {}
        for member in stop_area.members:

            if member.role == "platform":

                if isinstance(member, overpy.RelationNode):
                    member_osm_type = "node"
                elif isinstance(member, overpy.RelationWay):
                    member_osm_type = "way"

                identifier = member_osm_type + "/" + str(member.ref)

                if identifier in self.stops['regular']:

                    # Collect the Stop objects that are members
                    # of this Station
                    members[identifier] = self.stops['regular'][identifier]
                else:
                    logging.error("Station member was not found in data")
                    logging.error(" https://osm.org/relation/%s", stop_area.id)
                    logging.error(" https://osm.org/node/%s", member.ref)

        if len(members) < 1:
            # Stop areas with only one stop, are not stations they just
            # group different elements of one stop together.
            logging.error("Station with no members has been discarted:")
            logging.error(" https://osm.org/relation/%s", stop_area.id)
            return None

        elif len(members) == 1:
            logging.warning(
                "OSM stop area has only one platform and can't be used as a GTFS station:"
            )
            logging.warning(" https://osm.org/relation/%s", stop_area.id)
            return None

        # Check name of stop area
        if 'name' not in stop_area.tags:
            logging.warning(
                "Stop area without name. Please fix in OpenStreetMap:")
            logging.warning(" https://osm.org/relation/%s", stop_area.id)
            stop_area.name = self.stop_no_name
        else:
            stop_area.name = stop_area.tags["name"]

        # Calculate coordinates for stop area based on the center of it's
        # members
        stop_area.lat, stop_area.lon = Helper.get_center_of_nodes(
            members.values())

        # Move to Elements class, once attributes with defaults play well
        # with inheritance https://github.com/python-attrs/attrs/issues/38
        osm_url = "https://osm.org/" + str(osm_type) + "/" + str(stop_area.id)

        # Create and return Station object
        station = Station(osm_id=stop_area.id,
                          osm_type=osm_type,
                          osm_url=osm_url,
                          tags=stop_area.tags,
                          name=stop_area.name,
                          lat=stop_area.lat,
                          lon=stop_area.lon)
        station.set_members(members)

        logging.info(
            "Stop area (OSM) has been used to create a station (GTFS):\n")
        logging.info(" https://osm.org/relation/%s\n", str(stop_area.id))

        return station
    def add_trips_by_day(self, feed, line, service, route, horarios, day):

        # check if we even have service
        if horarios is None or len(horarios) == 0:
            return

        if isinstance(route, Line):
            # recurse into "Ida" and "Volta" routes
            for sub_route in route.get_itineraries():
                sub_route.duration = route.duration
                self.add_trips_by_day(feed, line, service, sub_route, horarios, day)
            return

        # have at least two stops
        if len(route.stops) < 2:
            sys.stderr.write("Skipping Route, has no stops: " + str(route) + "\n")
            return

        # check if we have a match for the first stop
        key = self.match_first_stops(route, horarios.keys())

        if key is None:
            # Do not print debug output here, because already done in route.match_first_stops()
            return

        if route.route_id == DEBUG_ROUTE:
            print "\n\n\n" + str(route)
            print day + " - " + key

        # get shape id
        shape_id = str(route.route_id)
        try:
            feed.GetShape(shape_id)
        except KeyError:
            shape = transitfeed.Shape(shape_id)
            for point in route.shape:
                shape.AddPoint(lat=float(point["lat"]), lon=float(point["lon"]))
            feed.AddShapeObject(shape)

        if len(horarios) > 1 and route.line is None:
            sys.stderr.write(
                "Route should have a master: [" + route.route_id + "] " + str(
                    route.osm_url) + "\n")

        for time_group in horarios[key]:
            for time_point in time_group:
                # parse first departure time
                start_time = datetime.strptime(time_point[0], "%H:%M")
                start_time = str(start_time.time())

                # calculate last arrival time for GTFS
                start_sec = transitfeed.TimeToSecondsSinceMidnight(start_time)
                factor = 1
                if len(horarios) > 1 and route.line is None:
                    # since this route has only one instead of two trips, double the duration
                    factor = 2
                end_sec = start_sec + route.duration.seconds * factor
                end_time = transitfeed.FormatSecondsSinceMidnight(end_sec)

                # TODO handle options
                # opts = time_point[1]

                trip = line.AddTrip(feed, headsign=route.name, service_period=service)
                # add empty attributes to make navitia happy
                trip.block_id = ""
                trip.wheelchair_accessible = ""
                trip.bikes_allowed = ""
                trip.shape_id = shape_id
                trip.direction_id = ""
                if route.route_id == DEBUG_ROUTE:
                    print "ADD TRIP " + str(trip.trip_id) + ":"
                self.add_trip_stops(feed, trip, route, start_time, end_time)

                # interpolate times, because Navitia can not handle this itself
                Helper.interpolate_stop_times(trip)
    def add_trips_to_feed(self, feed, data):
        self.service_weekday = feed.GetDefaultServicePeriod()
        self.service_weekday.SetStartDate(
            self.config['feed_info']['start_date'])
        self.service_weekday.SetEndDate(self.config['feed_info']['end_date'])
        self.service_weekday.SetWeekdayService(True)
        self.service_weekday.SetWeekendService(True)

        lines = data.routes
        for route_ref, line in sorted(lines.iteritems()):
            if not isinstance(line, Line):
                continue
            print("Generating schedule for line: " + route_ref)

            line_gtfs = feed.AddRoute(
                short_name=str(line.route_id),
                long_name=line.name,
                # we change the route_long_name with the 'from' and 'to' tags
                # of the last route as the route_master name tag contains
                # the line code (route_short_name)
                route_type="Bus",
                route_id=line.osm_id)
            line_gtfs.agency_id = feed.GetDefaultAgency().agency_id
            line_gtfs.route_desc = ""
            line_gtfs.route_color = "1779c2"
            line_gtfs.route_text_color = "ffffff"

            route_index = 0
            itineraries = line.get_itineraries()
            for a_route in itineraries:
                trip_gtfs = line_gtfs.AddTrip(feed)
                trip_gtfs.shape_id = self._add_shape_to_feed(
                    feed, a_route.osm_id, a_route)
                trip_gtfs.direction_id = route_index % 2
                route_index += 1

                if a_route.fr and a_route.to:
                    trip_gtfs.trip_headsign = a_route.to
                    line_gtfs.route_long_name = a_route.fr.decode(
                        'utf8') + " ↔ ".decode(
                        'utf8') + a_route.to.decode('utf8')

                DEFAULT_ROUTE_FREQUENCY = 30
                DEFAULT_TRAVEL_TIME = 120

                frequency = None
                if "frequency" in line.tags:
                    frequency = line.tags['frequency']
                try:
                    ROUTE_FREQUENCY = int(frequency)
                    if not ROUTE_FREQUENCY > 0:
                        print("frequency is invalid for route_master " + str(
                            line.osm_id))
                        ROUTE_FREQUENCY = DEFAULT_ROUTE_FREQUENCY
                except (ValueError, TypeError) as e:
                    print("frequency not a number for route_master " + str(
                            line.osm_id))
                    ROUTE_FREQUENCY = DEFAULT_ROUTE_FREQUENCY
                trip_gtfs.AddFrequency(
                    "05:00:00", "22:00:00", ROUTE_FREQUENCY * 60)
                if 'travel_time' in a_route.tags:
                    try:
                        TRAVEL_TIME = int(a_route.tags['travel_time'])
                        if not TRAVEL_TIME > 0:
                            print("travel_time is invalid for route " + str(
                                    a_route.osm_id))
                            TRAVEL_TIME = DEFAULT_TRAVEL_TIME
                    except (ValueError, TypeError) as e:
                        print("travel_time not a number for route " + str(
                                    a_route.osm_id))
                        TRAVEL_TIME = DEFAULT_TRAVEL_TIME
                else:
                    TRAVEL_TIME = DEFAULT_TRAVEL_TIME

                for index_stop, a_stop in enumerate(a_route.stops):
                    stop_id = a_stop.split('/')[-1]
                    departure_time = datetime(2008, 11, 22, 6, 0, 0)

                    if index_stop == 0:
                        trip_gtfs.AddStopTime(feed.GetStop(
                            str(stop_id)), stop_time=departure_time.strftime(
                                "%H:%M:%S"))
                    elif index_stop == len(a_route.stops) - 1:
                        departure_time += timedelta(minutes=TRAVEL_TIME)
                        trip_gtfs.AddStopTime(feed.GetStop(
                            str(stop_id)), stop_time=departure_time.strftime(
                                "%H:%M:%S"))
                    else:
                        trip_gtfs.AddStopTime(feed.GetStop(str(stop_id)))

                for secs, stop_time, is_timepoint in trip_gtfs.GetTimeInterpolatedStops():
                    if not is_timepoint:
                        stop_time.arrival_secs = secs
                        stop_time.departure_secs = secs
                        trip_gtfs.ReplaceStopTimeObject(stop_time)

                Helper.interpolate_stop_times(trip_gtfs)
Exemple #13
0
    def _add_itinerary_trips(self, feed, itinerary, line, trip_builder,
                             shape_id):
        """
        Add all trips of an itinerary to the GTFS feed.
        """
        # Obtain GTFS route to add trips to it.
        route = feed.GetRoute(line.route_id)
        trips_count = 0

        # Loop through each timeslot for a trip
        for trip in trip_builder['schedule']:
            gtfs_trip = route.AddTrip(
                feed,
                headsign=itinerary.to,
                service_period=trip_builder['service_period'])
            trips_count += 1
            search_idx = 0

            # Go through all stops of an itinerary
            for itinerary_stop_idx, itinerary_stop_id in enumerate(
                    itinerary.get_stops()):

                # Load full stop object
                try:
                    itinerary_stop = trip_builder['all_stops']['regular'][
                        itinerary_stop_id]
                except ValueError:
                    logging.warning("Itinerary (%s) misses a stop:",
                                    itinerary.route_url)
                    logging.warning(" Please review: %s", itinerary_stop_id)
                    continue

                try:
                    # Load respective GTFS stop object
                    gtfs_stop = feed.GetStop(str(itinerary_stop.stop_id))
                except ValueError:
                    logging.warning("Stop in itinerary was not found in GTFS.")
                    logging.warning(" %s", itinerary_stop.osm_url)
                    continue

                # Make sure we compare same unicode encoding
                if type(itinerary_stop.name) is str:
                    itinerary_stop.name = itinerary_stop.name.decode('utf-8')

                schedule_stop_idx = -1
                # Check if we have specific time information for this stop.
                try:
                    schedule_stop_idx = trip_builder['stops'].index(
                        itinerary_stop.name, search_idx)
                except ValueError:
                    if itinerary_stop.get_parent_station() is not None:
                        # If stop name not found, check for the parent_station name, too.
                        itinerary_station = trip_builder['all_stops'][
                            'stations'][str(
                                itinerary_stop.get_parent_station())]
                        if type(itinerary_station.name) is str:
                            itinerary_station.name = itinerary_station.name.decode(
                                'utf-8')
                        try:
                            schedule_stop_idx = trip_builder['stops'].index(
                                itinerary_station.name, search_idx)
                        except ValueError:
                            pass

                # Make sure the last stop of itinerary will keep being the last stop in GTFS
                last_stop_schedule = schedule_stop_idx == len(
                    trip_builder['stops']) - 1
                last_stop_itinerary = itinerary_stop_idx == len(
                    itinerary.get_stops()) - 1
                if last_stop_schedule != last_stop_itinerary:
                    schedule_stop_idx = -1

                if schedule_stop_idx != -1:
                    time = trip[schedule_stop_idx]
                    search_idx = schedule_stop_idx + 1

                    # Validate time information
                    try:
                        time_at_stop = str(
                            datetime.strptime(time, "%H:%M").time())
                    except ValueError:
                        logging.warning(
                            'Time "%s" for the stop was not valid:', time)
                        logging.warning(" %s - %s", itinerary_stop.name,
                                        itinerary_stop.osm_url)
                        break
                    gtfs_trip.AddStopTime(gtfs_stop, stop_time=time_at_stop)

                # Add stop without time information, too (we interpolate later)
                else:
                    try:
                        gtfs_trip.AddStopTime(gtfs_stop)
                    except transitfeed.problems.OtherProblem:
                        logging.warning(
                            "Could not add first stop to trip without time information."
                        )
                        logging.warning(" %s - %s", itinerary_stop.name,
                                        itinerary_stop.osm_url)
                        break

                # Add reference to shape
                gtfs_trip.shape_id = shape_id

                # Add empty attributes to make navitia happy
                gtfs_trip.block_id = ""
                gtfs_trip.wheelchair_accessible = ""
                gtfs_trip.bikes_allowed = ""
                gtfs_trip.direction_id = ""

            # Calculate all times of stops, which were added with no time
            Helper.interpolate_stop_times(gtfs_trip)
        return trips_count
Exemple #14
0
    def _add_itinerary_trips(self, feed, itinerary, line, trip_builder,
                             shape_id):
        """
        Add all trips of an itinerary to the GTFS feed.
        """
        # Obtain GTFS route to add trips to it.
        route = feed.GetRoute(line.route_id)
        trips_count = 0

        # Loop through each timeslot for a trip
        for trip in trip_builder['schedule']:
            gtfs_trip = route.AddTrip(
                feed,
                headsign=itinerary.to,
                service_period=trip_builder['service_period'])
            trips_count += 1

            # Go through all stops of an itinerary
            for itinerary_stop_id in itinerary.get_stops():

                # Load full stop object
                try:
                    itinerary_stop = trip_builder['all_stops']['regular'][
                        itinerary_stop_id]
                except ValueError:

                    sys.stderr.write("Itinerary (" + itinerary.route_url +
                                     ") misses a stop: \n")
                    sys.stderr.write("Please review: " + itinerary_stop_id +
                                     "\n")
                    continue

                try:
                    # Load respective GTFS stop object
                    gtfs_stop = feed.GetStop(str(itinerary_stop.stop_id))
                except ValueError:
                    print("Warning: Stop in itinerary was not found in GTFS.")
                    print(" " + itinerary_stop.osm_url)

                # Make sure we compare same unicode encoding
                if type(itinerary_stop.name) is str:
                    itinerary_stop.name = itinerary_stop.name.decode('utf-8')

                time = "-"
                # Check if we have specific time information for this stop.
                try:
                    time = trip[trip_builder['stops'].index(
                        itinerary_stop.name)]
                except ValueError:
                    pass

                # Validate time information
                if time != "-":
                    try:
                        time_at_stop = str(
                            datetime.strptime(time, "%H:%M").time())
                    except ValueError:
                        print('Warning: Time "' + time +
                              '" for the stop was not valid:')
                        print(" " + itinerary_stop.name + " - " +
                              itinerary_stop.osm_url)
                        break
                    gtfs_trip.AddStopTime(gtfs_stop, stop_time=time_at_stop)

                # Add stop without time information, too (we interpolate later)
                else:
                    try:
                        gtfs_trip.AddStopTime(gtfs_stop)
                    except ValueError:
                        print("Warning: Could not add first a stop to trip.")
                        print(" " + itinerary_stop.name + " - " +
                              itinerary_stop.osm_id)
                        break

                # Add reference to shape
                gtfs_trip.shape_id = shape_id

                # Add empty attributes to make navitia happy
                gtfs_trip.block_id = ""
                gtfs_trip.wheelchair_accessible = ""
                gtfs_trip.bikes_allowed = ""
                gtfs_trip.direction_id = ""

            # Calculate all times of stops, which were added with no time
            Helper.interpolate_stop_times(gtfs_trip)
        return trips_count