def __init__(self, limit_per_type, ignore_types=None): # {TYPE_WARNING: {"ClassName": BoundedProblemList()}} self._type_to_name_to_problist = { TYPE_WARNING: defaultdict(lambda: BoundedProblemList(limit_per_type)), TYPE_ERROR: defaultdict(lambda: BoundedProblemList(limit_per_type)) } self._ignore_types = ignore_types or set()
def __init__(self, limit_per_type): # {TYPE_WARNING: {"ClassName": BoundedProblemList()}} self._type_to_name_to_problist = { TYPE_WARNING: defaultdict(lambda: BoundedProblemList(limit_per_type)), TYPE_ERROR: defaultdict(lambda: BoundedProblemList(limit_per_type)) }
def GenerateDateTripsDeparturesList(self, date_start, date_end): """Return a list of (date object, number of trips, number of departures). The list is generated for dates in the range [date_start, date_end). Args: date_start: The first date in the list, a date object date_end: The first date after the list, a date object Returns: a list of (date object, number of trips, number of departures) tuples """ service_id_to_trips = defaultdict(lambda: 0) service_id_to_departures = defaultdict(lambda: 0) for trip in self.GetTripList(): headway_start_times = trip.GetFrequencyStartTimes() if headway_start_times: trip_runs = len(headway_start_times) else: trip_runs = 1 service_id_to_trips[trip.service_id] += trip_runs service_id_to_departures[trip.service_id] += ( (trip.GetCountStopTimes() - 1) * trip_runs) date_services = self.GetServicePeriodsActiveEachDate(date_start, date_end) date_trips = [] for date, services in date_services: day_trips = sum(service_id_to_trips[s.service_id] for s in services) day_departures = sum( service_id_to_departures[s.service_id] for s in services) date_trips.append((date, day_trips, day_departures)) return date_trips
def __init__(self, limit_per_type, ignore_types=None): # {TYPE_WARNING: {"ClassName": BoundedProblemList()}} self._type_to_name_to_problist = { TYPE_WARNING: defaultdict(lambda: BoundedProblemList(limit_per_type)), TYPE_ERROR: defaultdict(lambda: BoundedProblemList(limit_per_type)), TYPE_NOTICE: defaultdict(lambda: BoundedProblemList(limit_per_type)), } self._ignore_types = ignore_types or set()
def __init__(self, problem_reporter=None, memory_db=True, check_duplicate_trips=False, gtfs_factory=None, db_filename=None, create_db=True): if gtfs_factory is None: gtfs_factory = gtfsfactory.GetGtfsFactory() self._gtfs_factory = gtfs_factory # Map from table name to list of columns present in this schedule self._table_columns = {} self._agencies = {} self.stops = {} self.routes = {} self.trips = {} self.service_periods = {} self.fares = {} self.fare_zones = {} # represents the set of all known fare zones self._shapes = {} # shape_id to Shape # A map from transfer._ID() to a list of transfers. A list is used so # there can be more than one transfer with each ID. Once GTFS explicitly # prohibits duplicate IDs this might be changed to a simple dict of # Transfers. self._transfers = defaultdict(lambda: []) self._default_service_period = None self._default_agency = None if problem_reporter is None: self.problem_reporter = problems_module.default_problem_reporter else: self.problem_reporter = problem_reporter self._check_duplicate_trips = check_duplicate_trips self.ConnectDb(memory_db, db_filename, create_db)
def calendar_summary(schedule): today = datetime.date.today() summary_end_date = today + datetime.timedelta(days=60) start_date, end_date = schedule.get_date_range() if not start_date or not end_date: return {} start_date_object = transitfeed.date_string_to_date_object(start_date) end_date_object = transitfeed.date_string_to_date_object(end_date) if not start_date_object or not end_date_object: return {} # Get the list of trips only during the period the feed is active. # As such we have to check if it starts in the future and/or if # if it ends in less than 60 days. date_trips_departures = schedule.generate_date_trips_departures_list( max(today, start_date_object), min(summary_end_date, end_date_object)) if not date_trips_departures: return {} # Check that the dates which will be shown in summary agree with these # calculations. Failure implies a bug which should be fixed. It isn't good # for users to discover assertion failures but means it will likely be fixed. assert start_date <= date_trips_departures[0][0].strftime("%Y%m%d") assert end_date >= date_trips_departures[-1][0].strftime("%Y%m%d") # Generate a map from int number of trips in a day to a list of date objects # with that many trips. The list of dates is sorted. trips_dates = defaultdict(list) trips = 0 for date, day_trips, day_departures in date_trips_departures: trips += day_trips trips_dates[day_trips].append(date) mean_trips = trips / len(date_trips_departures) max_trips = max(trips_dates.keys()) min_trips = min(trips_dates.keys()) return { 'mean_trips': mean_trips, 'max_trips': max_trips, 'max_trips_dates': format_date_list(trips_dates[max_trips]), 'min_trips': min_trips, 'min_trips_dates': format_date_list(trips_dates[min_trips]), 'date_trips_departures': date_trips_departures, 'date_summary_range': "%s to %s" % (date_trips_departures[0][0].strftime("%a %b %d"), date_trips_departures[-1][0].strftime("%a %b %d")) }
def CalendarSummary(schedule): today = datetime.date.today() summary_end_date = today + datetime.timedelta(days=60) start_date, end_date = schedule.GetDateRange() if not start_date or not end_date: return {} try: start_date_object = transitfeed.DateStringToDateObject(start_date) end_date_object = transitfeed.DateStringToDateObject(end_date) except ValueError: return {} # Get the list of trips only during the period the feed is active. # As such we have to check if it starts in the future and/or if # if it ends in less than 60 days. date_trips_departures = schedule.GenerateDateTripsDeparturesList( max(today, start_date_object), min(summary_end_date, end_date_object)) if not date_trips_departures: return {} # Check that the dates which will be shown in summary agree with these # calculations. Failure implies a bug which should be fixed. It isn't good # for users to discover assertion failures but means it will likely be fixed. assert start_date <= date_trips_departures[0][0].strftime("%Y%m%d") assert end_date >= date_trips_departures[-1][0].strftime("%Y%m%d") # Generate a map from int number of trips in a day to a list of date objects # with that many trips. The list of dates is sorted. trips_dates = defaultdict(lambda: []) trips = 0 for date, day_trips, day_departures in date_trips_departures: trips += day_trips trips_dates[day_trips].append(date) mean_trips = trips / len(date_trips_departures) max_trips = max(trips_dates.keys()) min_trips = min(trips_dates.keys()) calendar_summary = {} calendar_summary['mean_trips'] = mean_trips calendar_summary['max_trips'] = max_trips calendar_summary['max_trips_dates'] = FormatDateList(trips_dates[max_trips]) calendar_summary['min_trips'] = min_trips calendar_summary['min_trips_dates'] = FormatDateList(trips_dates[min_trips]) calendar_summary['date_trips_departures'] = date_trips_departures calendar_summary['date_summary_range'] = "%s to %s" % ( date_trips_departures[0][0].strftime("%a %b %d"), date_trips_departures[-1][0].strftime("%a %b %d")) return calendar_summary
def ValidateTrips(self, problems): stop_types = {} # a dict mapping stop_id to [route_id, route_type, is_match] trips = {} # a dict mapping tuple to (route_id, trip_id) # a dict mapping block_id to a list of tuple of # (trip_id, first_arrival_secs, last_arrival_secs) trip_intervals_by_block_id = defaultdict(lambda: []) for trip in sorted(self.trips.values()): if trip.route_id not in self.routes: continue route_type = self.GetRoute(trip.route_id).route_type stop_ids = [] stop_times = trip.GetStopTimes(problems) for index, st in enumerate(stop_times): stop_id = st.stop.stop_id stop_ids.append(stop_id) # Check a stop if which belongs to both subway and bus. if (route_type == self._gtfs_factory.Route._ROUTE_TYPE_NAMES['Subway'] or route_type == self._gtfs_factory.Route._ROUTE_TYPE_NAMES['Bus']): if stop_id not in stop_types: stop_types[stop_id] = [trip.route_id, route_type, 0] elif (stop_types[stop_id][1] != route_type and stop_types[stop_id][2] == 0): stop_types[stop_id][2] = 1 if stop_types[stop_id][1] == \ self._gtfs_factory.Route._ROUTE_TYPE_NAMES['Subway']: subway_route_id = stop_types[stop_id][0] bus_route_id = trip.route_id else: subway_route_id = trip.route_id bus_route_id = stop_types[stop_id][0] problems.StopWithMultipleRouteTypes(st.stop.stop_name, stop_id, subway_route_id, bus_route_id) # We only care about trips with a block id if not util.IsEmpty(trip.block_id) and stop_times: first_arrival_secs = stop_times[0].arrival_secs last_departure_secs = stop_times[-1].departure_secs # The arrival and departure time of the first and last stop_time # SHOULD be set, but we need to handle the case where we're given # an invalid feed anyway if first_arrival_secs is not None and last_departure_secs is not None: # Create a trip interval tuple of the trip id and arrival time # intervals key = trip.block_id trip_intervals = trip_intervals_by_block_id[key] trip_interval = (trip, first_arrival_secs, last_departure_secs) trip_intervals.append(trip_interval) # Check duplicate trips which go through the same stops with same # service and start times. if self._check_duplicate_trips: if not stop_ids or not stop_times: continue key = (trip.service_id, stop_times[0].arrival_time, str(stop_ids)) if key not in trips: trips[key] = (trip.route_id, trip.trip_id) else: problems.DuplicateTrip(trips[key][1], trips[key][0], trip.trip_id, trip.route_id) # Now that we've generated our block trip intervls, we can check for # overlaps in the intervals self.ValidateBlocks(problems, trip_intervals_by_block_id)