def AddStopTimeObject(self, stoptime, schedule=None, problems=None):
        """Add a StopTime object to the end of this trip.

    Args:
      stoptime: A StopTime object. Should not be reused in multiple trips.
      schedule: Schedule object containing this trip which must be
      passed to Trip.__init__ or here
      problems: ProblemReporter object for validating the StopTime in its new
      home

    Returns:
      None
    """
        if schedule is None:
            schedule = self._schedule
        if schedule is None:
            warnings.warn(
                "No longer supported. _schedule attribute is used to get "
                "stop_times table", DeprecationWarning)
        if problems is None:
            problems = schedule.problem_reporter

        if stoptime._cursor_factory is None:
            stoptime._cursor_factory = schedule

        new_secs = stoptime.GetTimeSecs()
        cursor = schedule._connection.cursor()
        cursor.execute(
            "SELECT max(stop_sequence), max(arrival_secs), "
            "max(departure_secs) FROM stop_times WHERE trip_id=?",
            (self.trip_id, ))
        row = cursor.fetchone()
        if row[0] is None:
            # This is the first stop_time of the trip
            stoptime.stop_sequence = 1
            if new_secs == None:
                problems.OtherProblem(
                    'No time for first StopTime of trip_id "%s"' %
                    (self.trip_id, ))
        else:
            stoptime.stop_sequence = row[0] + 1
            prev_secs = max(row[1], row[2])
            if new_secs != None and new_secs < prev_secs:
                problems.OtherProblem(
                    'out of order stop time for stop_id=%s trip_id=%s %s < %s'
                    % (util.EncodeUnicode(
                        stoptime.stop_id), util.EncodeUnicode(self.trip_id),
                       util.FormatSecondsSinceMidnight(new_secs),
                       util.FormatSecondsSinceMidnight(prev_secs)))
        self._AddStopTimeObjectUnordered(stoptime)
Exemple #2
0
 def _Report(self, e):
   levels = {TYPE_ERROR: logging.ERROR, TYPE_WARNING: logging.WARNING, TYPE_NOTICE: logging.INFO}
   context = e.FormatContext()
   if context:
     #logging.log(levels[e.type],context)
     logger.log(levels[e.type],context)
     #exit(1)
   #logging.log(levels[e.type],util.EncodeUnicode(self._LineWrap(e.FormatProblem(), 78)))
   logger.log(levels[e.type],util.EncodeUnicode(self._LineWrap(e.FormatProblem(), 78)))
Exemple #3
0
 def GetDictToFormat(self):
     """Return a copy of self as a dict, suitable for passing to FormatProblem"""
     d = {}
     for k, v in self.__dict__.items():
         # TODO: Better handling of unicode/utf-8 within Schedule objects.
         # Concatinating a unicode and utf-8 str object causes an exception such
         # as "UnicodeDecodeError: 'ascii' codec can't decode byte ..." as python
         # tries to convert the str to a unicode. To avoid that happening within
         # the problem reporter convert all unicode attributes to utf-8.
         # Currently valid utf-8 fields are converted to unicode in _ReadCsvDict.
         # Perhaps all fields should be left as utf-8.
         d[k] = util.EncodeUnicode(v)
     return d
Exemple #4
0
  def ValidateStops(self, problems, validate_children):
    # Check for stops that aren't referenced by any trips and broken
    # parent_station references. Also check that the parent station isn't too
    # far from its child stops.
    for stop in self.stops.values():
      if validate_children:
        stop.Validate(problems)
      cursor = self._connection.cursor()
      cursor.execute("SELECT count(*) FROM stop_times WHERE stop_id=? LIMIT 1",
                     (stop.stop_id,))
      count = cursor.fetchone()[0]
      if stop.location_type == 0 and count == 0:
          problems.UnusedStop(stop.stop_id, stop.stop_name)
      elif stop.location_type == 1 and count != 0:
          problems.UsedStation(stop.stop_id, stop.stop_name)

      if stop.location_type != 1 and stop.parent_station:
        if stop.parent_station not in self.stops:
          problems.InvalidValue("parent_station",
                                util.EncodeUnicode(stop.parent_station),
                                "parent_station '%s' not found for stop_id "
                                "'%s' in stops.txt" %
                                (util.EncodeUnicode(stop.parent_station),
                                 util.EncodeUnicode(stop.stop_id)))
        elif self.stops[stop.parent_station].location_type != 1:
          problems.InvalidValue("parent_station",
                                util.EncodeUnicode(stop.parent_station),
                                "parent_station '%s' of stop_id '%s' must "
                                "have location_type=1 in stops.txt" %
                                (util.EncodeUnicode(stop.parent_station),
                                 util.EncodeUnicode(stop.stop_id)))
        else:
          parent_station = self.stops[stop.parent_station]
          distance = util.ApproximateDistanceBetweenStops(stop, parent_station)
          if distance > problems_module.MAX_DISTANCE_BETWEEN_STOP_AND_PARENT_STATION_ERROR:
            problems.StopTooFarFromParentStation(
                stop.stop_id, stop.stop_name, parent_station.stop_id,
                parent_station.stop_name, distance, problems_module.TYPE_ERROR)
          elif distance > problems_module.MAX_DISTANCE_BETWEEN_STOP_AND_PARENT_STATION_WARNING:
            problems.StopTooFarFromParentStation(
                stop.stop_id, stop.stop_name, parent_station.stop_id,
                parent_station.stop_name, distance, 
                problems_module.TYPE_WARNING)
Exemple #5
0
 def ValidateNearbyStops(self, problems):
   # Check for stops that might represent the same location (specifically,
   # stops that are less that 2 meters apart) First filter out stops without a
   # valid lat and lon. Then sort by latitude, then find the distance between
   # each pair of stations within 2 meters latitude of each other. This avoids
   # doing n^2 comparisons in the average case and doesn't need a spatial
   # index.
   sorted_stops = filter(lambda s: s.stop_lat and s.stop_lon,
                         self.GetStopList())
   sorted_stops.sort(key=(lambda x: x.stop_lat))
   TWO_METERS_LAT = 0.000018
   for index, stop in enumerate(sorted_stops[:-1]):
     index += 1
     while ((index < len(sorted_stops)) and
            ((sorted_stops[index].stop_lat - stop.stop_lat) < TWO_METERS_LAT)):
       distance  = util.ApproximateDistanceBetweenStops(stop, 
                                                        sorted_stops[index])
       if distance < 2:
         other_stop = sorted_stops[index]
         if stop.location_type == 0 and other_stop.location_type == 0:
           problems.StopsTooClose(
               util.EncodeUnicode(stop.stop_name),
               util.EncodeUnicode(stop.stop_id),
               util.EncodeUnicode(other_stop.stop_name),
               util.EncodeUnicode(other_stop.stop_id), distance)
         elif stop.location_type == 1 and other_stop.location_type == 1:
           problems.StationsTooClose(
               util.EncodeUnicode(stop.stop_name), 
               util.EncodeUnicode(stop.stop_id),
               util.EncodeUnicode(other_stop.stop_name),
               util.EncodeUnicode(other_stop.stop_id), distance)
         elif (stop.location_type in (0, 1) and
               other_stop.location_type  in (0, 1)):
           if stop.location_type == 0 and other_stop.location_type == 1:
             this_stop = stop
             this_station = other_stop
           elif stop.location_type == 1 and other_stop.location_type == 0:
             this_stop = other_stop
             this_station = stop
           if this_stop.parent_station != this_station.stop_id:
             problems.DifferentStationTooClose(
                 util.EncodeUnicode(this_stop.stop_name),
                 util.EncodeUnicode(this_stop.stop_id),
                 util.EncodeUnicode(this_station.stop_name),
                 util.EncodeUnicode(this_station.stop_id), distance)
       index += 1
Exemple #6
0
  def WriteGoogleTransitFeed(self, file):
    """Output this schedule as a Google Transit Feed in file_name.

    Args:
      file: path of new feed file (a string) or a file-like object

    Returns:
      None
    """
    # Compression type given when adding each file
    archive = zipfile.ZipFile(file, 'w')

    if 'agency' in self._table_columns:
      agency_string = StringIO.StringIO()
      writer = util.CsvUnicodeWriter(agency_string)
      columns = self.GetTableColumns('agency')
      writer.writerow(columns)
      for a in self._agencies.values():
        writer.writerow([util.EncodeUnicode(a[c]) for c in columns])
      self._WriteArchiveString(archive, 'agency.txt', agency_string)

    calendar_dates_string = StringIO.StringIO()
    writer = util.CsvUnicodeWriter(calendar_dates_string)
    writer.writerow(
        self._gtfs_factory.ServicePeriodException._FIELD_NAMES)
    has_data = False
    for period in self.service_periods.values():
      for row in period.GenerateCalendarDatesFieldValuesTuples():
        has_data = True
        writer.writerow(row)
    wrote_calendar_dates = False
    if has_data:
      wrote_calendar_dates = True
      self._WriteArchiveString(archive, 'calendar_dates.txt',
                               calendar_dates_string)

    calendar_string = StringIO.StringIO()
    writer = util.CsvUnicodeWriter(calendar_string)
    writer.writerow(self._gtfs_factory.ServicePeriod._FIELD_NAMES)
    has_data = False
    for s in self.service_periods.values():
      row = s.GetCalendarFieldValuesTuple()
      if row:
        has_data = True
        writer.writerow(row)
    if has_data or not wrote_calendar_dates:
      self._WriteArchiveString(archive, 'calendar.txt', calendar_string)

    if 'stops' in self._table_columns:
      stop_string = StringIO.StringIO()
      writer = util.CsvUnicodeWriter(stop_string)
      columns = self.GetTableColumns('stops')
      writer.writerow(columns)
      for s in self.stops.values():
        writer.writerow([util.EncodeUnicode(s[c]) for c in columns])
      self._WriteArchiveString(archive, 'stops.txt', stop_string)

    if 'routes' in self._table_columns:
      route_string = StringIO.StringIO()
      writer = util.CsvUnicodeWriter(route_string)
      columns = self.GetTableColumns('routes')
      writer.writerow(columns)
      for r in self.routes.values():
        writer.writerow([util.EncodeUnicode(r[c]) for c in columns])
      self._WriteArchiveString(archive, 'routes.txt', route_string)

    if 'trips' in self._table_columns:
      trips_string = StringIO.StringIO()
      writer = util.CsvUnicodeWriter(trips_string)
      columns = self.GetTableColumns('trips')
      writer.writerow(columns)
      for t in self.trips.values():
        writer.writerow([util.EncodeUnicode(t[c]) for c in columns])
      self._WriteArchiveString(archive, 'trips.txt', trips_string)

    # write frequencies.txt (if applicable)
    headway_rows = []
    for trip in self.GetTripList():
      headway_rows += trip.GetFrequencyOutputTuples()
    if headway_rows:
      headway_string = StringIO.StringIO()
      writer = util.CsvUnicodeWriter(headway_string)
      writer.writerow(self._gtfs_factory.Frequency._FIELD_NAMES)
      writer.writerows(headway_rows)
      self._WriteArchiveString(archive, 'frequencies.txt', headway_string)

    # write fares (if applicable)
    if self.GetFareAttributeList():
      fare_string = StringIO.StringIO()
      writer = util.CsvUnicodeWriter(fare_string)
      writer.writerow(self._gtfs_factory.FareAttribute._FIELD_NAMES)
      writer.writerows(
          f.GetFieldValuesTuple() for f in self.GetFareAttributeList())
      self._WriteArchiveString(archive, 'fare_attributes.txt', fare_string)

    # write fare rules (if applicable)
    rule_rows = []
    for fare in self.GetFareAttributeList():
      for rule in fare.GetFareRuleList():
        rule_rows.append(rule.GetFieldValuesTuple())
    if rule_rows:
      rule_string = StringIO.StringIO()
      writer = util.CsvUnicodeWriter(rule_string)
      writer.writerow(self._gtfs_factory.FareRule._FIELD_NAMES)
      writer.writerows(rule_rows)
      self._WriteArchiveString(archive, 'fare_rules.txt', rule_string)
    stop_times_string = StringIO.StringIO()
    writer = util.CsvUnicodeWriter(stop_times_string)
    writer.writerow(self._gtfs_factory.StopTime._FIELD_NAMES)
    for t in self.trips.values():
      writer.writerows(t._GenerateStopTimesTuples())
    self._WriteArchiveString(archive, 'stop_times.txt', stop_times_string)

    # write shapes (if applicable)
    shape_rows = []
    for shape in self.GetShapeList():
      seq = 1
      for (lat, lon, dist) in shape.points:
        shape_rows.append((shape.shape_id, lat, lon, seq, dist))
        seq += 1
    if shape_rows:
      shape_string = StringIO.StringIO()
      writer = util.CsvUnicodeWriter(shape_string)
      writer.writerow(self._gtfs_factory.ShapePoint._FIELD_NAMES)
      writer.writerows(shape_rows)
      self._WriteArchiveString(archive, 'shapes.txt', shape_string)

    if 'transfers' in self._table_columns:
      transfer_string = StringIO.StringIO()
      writer = util.CsvUnicodeWriter(transfer_string)
      columns = self.GetTableColumns('transfers')
      writer.writerow(columns)
      for t in self.GetTransferIter():
        writer.writerow([util.EncodeUnicode(t[c]) for c in columns])
      self._WriteArchiveString(archive, 'transfers.txt', transfer_string)

    archive.close()
Exemple #7
0
 def _Report(self, e):
     context = e.FormatContext()
     if context:
         print context
     print util.EncodeUnicode(self._LineWrap(e.FormatProblem(), 78))