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 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)
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)
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)
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
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