Beispiel #1
0
class FeedInfo(Base):
    """Information about the feed"""
    feed = models.ForeignKey('Feed')
    publisher_name = models.CharField(
        max_length=255,
        help_text="Full name of organization that publishes the feed.")
    publisher_url = models.URLField(
        help_text="URL of the feed publisher's organization.")
    lang = models.CharField(
        max_length=20,
        help_text="IETF BCP 47 language code for text in field.")
    start_date = models.DateField(
        null=True,
        blank=True,
        help_text="Date that feed starts providing reliable data.")
    end_date = models.DateField(
        null=True,
        blank=True,
        help_text="Date that feed stops providing reliable data.")
    version = models.CharField(max_length=255,
                               blank=True,
                               help_text="Version of feed.")

    def __unicode__(self):
        return u'%s-%s' % (self.feed.id, self.publisher_name)

    class Meta:
        db_table = 'multigtfs_feedinfo'
        app_label = 'multigtfs'
        verbose_name_plural = "feed info"

    _column_map = (('feed_publisher_name',
                    'publisher_name'), ('feed_publisher_url', 'publisher_url'),
                   ('feed_lang', 'lang'), ('feed_start_date', 'start_date'),
                   ('feed_end_date', 'end_date'), ('feed_version', 'version'))
Beispiel #2
0
class Agency(Base):
    """One or more transit agencies that provide the data in this feed.

    Maps to agency.txt in the GTFS feed.
    """
    feed = models.ForeignKey('Feed')
    agency_id = models.CharField(
        max_length=255, blank=True, db_index=True,
        help_text="Unique identifier for transit agency")
    name = models.CharField(
        max_length=255,
        help_text="Full name of the transit agency")
    url = models.URLField(
        blank=True, help_text="URL of the transit agency")
    timezone = models.CharField(
        max_length=255,
        help_text="Timezone of the agency")
    lang = models.CharField(
        max_length=2, blank=True,
        help_text="ISO 639-1 code for the primary language")
    phone = models.CharField(
        max_length=255, blank=True,
        help_text="Voice telephone number")
    fare_url = models.URLField(
        blank=True, help_text="URL for purchasing tickets online")
    extra_data = JSONField(default={}, blank=True, null=True)

    def __str__(self):
        return u"%d-%s" % (self.feed.id, self.agency_id)

    class Meta:
        db_table = 'agency'
        app_label = 'multigtfs'
        verbose_name_plural = "agencies"

    # GTFS column names to fields, used by Base for import/export
    _column_map = (
        ('agency_id', 'agency_id'),
        ('agency_name', 'name'),
        ('agency_url', 'url'),
        ('agency_timezone', 'timezone'),
        ('agency_lang', 'lang'),
        ('agency_phone', 'phone'),
        ('agency_fare_url', 'fare_url')
    )
    _filename = 'agency.txt'
    _unique_fields = ('agency_id',)
Beispiel #3
0
class Route(Base):
    """A transit route"""

    feed = models.ForeignKey('Feed')
    route_id = models.CharField(
        max_length=255, db_index=True,
        help_text="Unique identifier for route.")
    agency = models.ForeignKey(
        'Agency', null=True, blank=True, help_text="Agency for this route.")
    short_name = models.CharField(
        max_length=10,
        help_text="Short name of the route")
    long_name = models.CharField(
        max_length=255,
        help_text="Long name of the route")
    desc = models.TextField(
        blank=True,
        help_text="Long description of a route")
    rtype = models.IntegerField(
        choices=((0, 'Tram, Streetcar, or Light rail'),
                 (1, 'Subway or Metro'),
                 (2, 'Rail'),
                 (3, 'Bus'),
                 (4, 'Ferry'),
                 (5, 'Cable car'),
                 (6, 'Gondola or Suspended cable car'),
                 (7, 'Funicular')),
        help_text='Type of transportation used on route')
    url = models.URLField(
        blank=True, help_text="Web page about for the route")
    color = models.CharField(
        max_length=6, blank=True,
        help_text="Color of route in hex")
    text_color = models.CharField(
        max_length=6, blank=True,
        help_text="Color of route text in hex")

    def __unicode__(self):
        return u"%d-%s" % (self.feed.id, self.route_id)

    class Meta:
        db_table = 'route'
        app_label = 'multigtfs'

    _column_map = (
        ('route_id', 'route_id'),
        ('agency_id', 'agency__agency_id'),
        ('route_short_name', 'short_name'),
        ('route_long_name', 'long_name'),
        ('route_desc', 'desc'),
        ('route_type', 'rtype'),
        ('route_url', 'url'),
        ('route_color', 'color'),
        ('route_text_color', 'text_color')
    )
    _sort_order = ('route_id', 'short_name')
class FeedInfo(Base):
    """Information about the feed

    Implements feed_info.txt in the GTFS feed.
    """
    feed = models.ForeignKey('Feed', on_delete=models.CASCADE)
    publisher_name = models.CharField(
        max_length=255,
        help_text="Full name of organization that publishes the feed.")
    publisher_url = models.URLField(
        help_text="URL of the feed publisher's organization.")
    lang = models.CharField(
        "language",
        max_length=20,
        help_text="IETF BCP 47 language code for text in field.")
    start_date = models.DateField(
        null=True,
        blank=True,
        help_text="Date that feed starts providing reliable data.")
    end_date = models.DateField(
        null=True,
        blank=True,
        help_text="Date that feed stops providing reliable data.")
    version = models.CharField(max_length=255,
                               blank=True,
                               help_text="Version of feed.")
    extra_data = JSONField(default={}, blank=True, null=True)

    def __str__(self):
        return '%s-%s' % (self.feed.id, self.publisher_name)

    class Meta:
        db_table = 'feed_info'
        app_label = 'multigtfs'
        verbose_name_plural = "feed info"

    _column_map = (('feed_publisher_name',
                    'publisher_name'), ('feed_publisher_url', 'publisher_url'),
                   ('feed_lang', 'lang'), ('feed_start_date', 'start_date'),
                   ('feed_end_date', 'end_date'), ('feed_version', 'version'))
    _filename = 'feed_info.txt'
    _unique_fields = ('feed_publisher_name', )
Beispiel #5
0
class Route(Base):
    """A transit route"""

    feed = models.ForeignKey('Feed')
    route_id = models.CharField(max_length=255,
                                db_index=True,
                                help_text="Unique identifier for route.")
    agency = models.ForeignKey('Agency',
                               null=True,
                               blank=True,
                               help_text="Agency for this route.")
    short_name = models.CharField(max_length=63,
                                  help_text="Short name of the route")
    long_name = models.CharField(max_length=255,
                                 help_text="Long name of the route")
    desc = models.TextField(blank=True,
                            help_text="Long description of a route")
    rtype = models.IntegerField(
        choices=((0, 'Tram, Streetcar, or Light rail'), (1, 'Subway or Metro'),
                 (2, 'Rail'), (3, 'Bus'), (4, 'Ferry'), (5, 'Cable car'),
                 (6, 'Gondola or Suspended cable car'), (7, 'Funicular')),
        help_text='Type of transportation used on route')
    url = models.URLField(blank=True, help_text="Web page about for the route")
    color = models.CharField(max_length=6,
                             blank=True,
                             help_text="Color of route in hex")
    text_color = models.CharField(max_length=6,
                                  blank=True,
                                  help_text="Color of route text in hex")
    geometry = models.MultiLineStringField(null=True,
                                           blank=True,
                                           help_text='Geometry cache of Trips')

    def update_geometry(self):
        """Update the geometry from the Trips"""
        original = self.geometry
        trips = self.trip_set.exclude(geometry=None)
        unique_coords = set()
        unique_geom = list()
        for t in trips:
            coords = t.geometry.coords
            if coords not in unique_coords:
                unique_coords.add(coords)
                unique_geom.append(t.geometry)
        self.geometry = MultiLineString(unique_geom)
        if self.geometry != original:
            self.save()

    def __unicode__(self):
        return u"%d-%s" % (self.feed.id, self.route_id)

    def stop_set(self):
        stoptimes = itertools.chain(*[
            trip.stoptime_set.all().distinct('stop')
            for trip in self.trip_set.all()
        ])
        return set([stoptime.stop for stoptime in stoptimes])

    class Meta:
        db_table = 'multigtfs_route'
        app_label = 'multigtfs'

    _column_map = (('route_id', 'route_id'),
                   ('agency_id', 'agency__agency_id'), ('route_short_name',
                                                        'short_name'),
                   ('route_long_name', 'long_name'), ('route_desc', 'desc'),
                   ('route_type', 'rtype'), ('route_url', 'url'),
                   ('route_color', 'color'), ('route_text_color',
                                              'text_color'))
    _sort_order = ('route_id', 'short_name')
Beispiel #6
0
class Stop(Base):
    """A stop or station"""
    feed = models.ForeignKey('Feed')
    stop_id = models.CharField(
        max_length=255,
        db_index=True,
        help_text="Unique identifier for a stop or station.")
    code = models.CharField(
        max_length=255,
        blank=True,
        help_text="Uniquer identifier (short text or number) for passengers.")
    name = models.CharField(max_length=255,
                            help_text="Name of stop in local vernacular.")
    desc = models.CharField("description",
                            max_length=255,
                            blank=True,
                            help_text='Description of a stop.')
    point = models.PointField(
        help_text='WGS 84 latitude/longitude of stop or station')
    zone = models.ForeignKey('Zone',
                             null=True,
                             blank=True,
                             help_text="Fare zone for a stop ID.")
    url = models.URLField(blank=True, help_text="URL for the stop")
    location_type = models.CharField(max_length=1,
                                     blank=True,
                                     choices=(('0', 'Stop'), ('1', 'Station')),
                                     help_text="Is this a stop or station?")
    parent_station = models.ForeignKey(
        'Stop',
        null=True,
        blank=True,
        help_text="The station associated with the stop")
    timezone = models.CharField(max_length=255,
                                blank=True,
                                help_text="Timezone of the stop")
    wheelchair_boarding = models.CharField(
        max_length=1,
        blank=True,
        choices=(('0', 'No information'), ('1', 'Some wheelchair boarding'),
                 ('2', 'No wheelchair boarding')),
        help_text='Is wheelchair boarding possible?')
    extra_data = JSONField(default={}, blank=True, null=True)

    def __str__(self):
        return "%d-%s" % (self.feed_id, self.stop_id)

    def getlon(self):
        return self.point[0] if self.point else 0.0

    def setlon(self, value):
        if self.point:
            self.point[0] = value
        else:
            self.point = "POINT(%s 0)" % value

    lon = property(getlon, setlon, doc="WGS 84 longitude of stop or station")

    def getlat(self):
        return self.point[1] if self.point else 0.0

    def setlat(self, value):
        if self.point:
            self.point[1] = value
        else:
            self.point = "POINT(0 %s)" % value

    lat = property(getlat, setlat, doc="WGS 84 latitude of stop or station")

    def __init__(self, *args, **kwargs):
        lat = kwargs.pop('lat', None)
        lon = kwargs.pop('lon', None)
        if lat is not None or lon is not None:
            assert kwargs.get('point') is None
            msg = "Setting Stop location with lat and lon is deprecated"
            warnings.warn(msg, DeprecationWarning)
            kwargs['point'] = "POINT(%s %s)" % (lon or 0.0, lat or 0.0)
        super(Stop, self).__init__(*args, **kwargs)

    class Meta:
        db_table = 'stop'
        app_label = 'multigtfs'

    _column_map = (
        ('stop_id', 'stop_id'),
        ('stop_code', 'code'),
        ('stop_name', 'name'),
        ('stop_desc', 'desc'),
        ('stop_lat', 'point[1]'),
        ('stop_lon', 'point[0]'),
        ('zone_id', 'zone__zone_id'),
        ('stop_url', 'url'),
        ('location_type', 'location_type'),
        ('parent_station', 'parent_station__stop_id'),
        ('stop_timezone', 'timezone'),
        ('wheelchair_boarding', 'wheelchair_boarding'),
    )
    _filename = 'stops.txt'
    _unique_fields = ('stop_id', )

    @classmethod
    def import_txt(cls, txt_file, feed):
        '''Import from a stops.txt file

        Stations need to be imported before stops
        '''

        txt = txt_file.read()

        def is_station(pairs):
            '''Does the row represent a station?'''
            for name, val in pairs:
                if name == 'location_type':
                    return val == '1'
            return False

        logger.info("Importing station stops")
        stations = super(Stop, cls).import_txt(StringIO(txt), feed, is_station)
        logger.info("Imported %d station stops", stations)

        def is_stop(pairs):
            '''Does the row represent a stop?'''
            for name, val in pairs:
                if name == 'location_type':
                    return val != '1'
            return True

        logger.info("Importing non-station stops")
        stops = super(Stop, cls).import_txt(StringIO(txt), feed, is_stop)
        logger.info("Imported %d non-station stops", stops)
        return stations + stops
class Route(Base):
    """A transit route

    Maps to route.txt in the GTFS feed.
    """

    feed = models.ForeignKey('Feed', on_delete=models.CASCADE)
    route_id = models.CharField(max_length=255,
                                db_index=True,
                                help_text="Unique identifier for route.")
    agency = models.ForeignKey('Agency',
                               null=True,
                               blank=True,
                               on_delete=models.SET_NULL,
                               help_text="Agency for this route.")
    short_name = models.CharField(max_length=63,
                                  help_text="Short name of the route")
    long_name = models.CharField(max_length=255,
                                 help_text="Long name of the route")
    desc = models.TextField("description",
                            blank=True,
                            help_text="Long description of a route")
    rtype = models.IntegerField(
        "route type",
        choices=((0, 'Tram, Streetcar, or Light rail'), (1, 'Subway or Metro'),
                 (2, 'Rail'), (3, 'Bus'), (4, 'Ferry'), (5, 'Cable car'),
                 (6, 'Gondola or Suspended cable car'), (7, 'Funicular')),
        help_text='Type of transportation used on route')
    url = models.URLField(blank=True, help_text="Web page about for the route")
    color = models.CharField(max_length=6,
                             blank=True,
                             help_text="Color of route in hex")
    text_color = models.CharField(max_length=6,
                                  blank=True,
                                  help_text="Color of route text in hex")
    geometry = models.MultiLineStringField(null=True,
                                           blank=True,
                                           help_text='Geometry cache of Trips')
    extra_data = JSONField(default={}, blank=True, null=True)

    def update_geometry(self):
        """Update the geometry from the Trips"""
        original = self.geometry
        trips = self.trip_set.exclude(geometry__isnull=True)
        unique_coords = set()
        unique_geom = list()
        for t in trips:
            coords = t.geometry.coords
            if coords not in unique_coords:
                unique_coords.add(coords)
                unique_geom.append(t.geometry)
        self.geometry = MultiLineString(unique_geom)
        if self.geometry != original:
            self.save()

    def __str__(self):
        return "%d-%s" % (self.feed.id, self.route_id)

    class Meta:
        db_table = 'route'
        app_label = 'multigtfs'

    _column_map = (('route_id', 'route_id'),
                   ('agency_id', 'agency__agency_id'), ('route_short_name',
                                                        'short_name'),
                   ('route_long_name', 'long_name'), ('route_desc', 'desc'),
                   ('route_type', 'rtype'), ('route_url', 'url'),
                   ('route_color', 'color'), ('route_text_color',
                                              'text_color'))
    _filename = 'routes.txt'
    _sort_order = ('route_id', 'short_name')
    _unique_fields = ('route_id', )
Beispiel #8
0
class Stop(Base):
    """A stop or station"""
    feed = models.ForeignKey('Feed')
    stop_id = models.CharField(
        max_length=255,
        db_index=True,
        help_text="Unique identifier for a stop or station.")
    code = models.CharField(
        max_length=255,
        blank=True,
        help_text="Uniquer identifier (short text or number) for passengers.")
    name = models.CharField(max_length=255,
                            help_text="Name of stop in local vernacular.")
    desc = models.CharField(max_length=255,
                            blank=True,
                            help_text='Description of a stop.')
    point = models.PointField(
        geography=MULTIGTFS_USE_GEOGRAPHY,
        srid=MULTIGTFS_SRID,
        help_text='WGS 84 latitude/longitude of stop or station')
    zone = models.ForeignKey('Zone',
                             null=True,
                             blank=True,
                             help_text="Fare zone for a stop ID.")
    url = models.URLField(blank=True, help_text="URL for the stop")
    location_type = models.CharField(max_length=1,
                                     blank=True,
                                     choices=(('0', 'Stop'), ('1', 'Station')),
                                     help_text="Is this a stop or station?")
    parent_station = models.ForeignKey(
        'Stop',
        null=True,
        blank=True,
        help_text="The station associated with the stop")
    timezone = models.CharField(max_length=255,
                                blank=True,
                                help_text="Timezone of the stop")
    wheelchair_boarding = models.CharField(
        max_length=1,
        blank=True,
        choices=(('0', '0'), ('1', '1'), ('2', '2')),
        help_text=
        "Whether wheelchair boardings are possible from the specified stop or station"
    )

    def __unicode__(self):
        return u"%d-%s" % (self.feed.id, self.stop_id)

    def getlon(self):
        return self.point[0] if self.point else 0.0

    def setlon(self, value):
        if self.point:
            self.point[0] = value
        else:
            self.point = "POINT(%s 0)" % value

    lon = property(getlon, setlon, doc="WGS 84 longitude of stop or station")

    def getlat(self):
        return self.point[1] if self.point else 0.0

    def setlat(self, value):
        if self.point:
            self.point[1] = value
        else:
            self.point = "POINT(0 %s)" % value

    lat = property(getlat, setlat, doc="WGS 84 latitude of stop or station")

    def __init__(self, *args, **kwargs):
        lat = kwargs.pop('lat', None)
        lon = kwargs.pop('lon', None)
        if lat is not None or lon is not None:
            assert kwargs.get('point') is None
            msg = "Setting Stop location with lat and lon is deprecated"
            warnings.warn(msg, DeprecationWarning)
            kwargs['point'] = "POINT(%s %s)" % (lon or 0.0, lat or 0.0)
        super(Stop, self).__init__(*args, **kwargs)

    class Meta:
        db_table = 'stop'
        app_label = 'multigtfs'

    _column_map = (('stop_id', 'stop_id'), ('stop_code', 'code'),
                   ('stop_name', 'name'), ('stop_desc', 'desc'), ('stop_lat',
                                                                  'point[1]'),
                   ('stop_lon', 'point[0]'), ('zone_id', 'zone__zone_id'),
                   ('stop_url', 'url'), ('location_type', 'location_type'),
                   ('parent_station', 'parent_station__stop_id'),
                   ('stop_timezone', 'timezone'), ('wheelchair_boarding',
                                                   'wheelchair_boarding'))

    @classmethod
    def import_txt(cls, txt_file, feed):
        '''Import from a stops.txt file

        Stations need to be imported before stops
        '''
        def writeheader(writer):
            '''
            Write the header row for a DictWriter CSV file

            This is a member function of DictWriter in Python 2.7
            '''
            writer.writerow(dict((fn, fn) for fn in writer.fieldnames))

        txt = txt_file.read()
        fieldnames, _ = zip(*cls._column_map)
        has_stations = False
        stations_csv = StringIO.StringIO()
        stations = DictWriter(stations_csv, fieldnames)
        has_stops = False
        stops_csv = StringIO.StringIO()
        stops = DictWriter(stops_csv, fieldnames)
        for row in DictReader(StringIO.StringIO(txt)):
            if row.get('location_type') == '1':
                if not has_stations:
                    writeheader(stations)
                    has_stations = True
                stations.writerow(row)
            else:
                if not has_stops:
                    writeheader(stops)
                    has_stops = True
                stops.writerow(row)
        if has_stations:
            super(Stop,
                  cls).import_txt(StringIO.StringIO(stations_csv.getvalue()),
                                  feed)
        if has_stops:
            super(Stop,
                  cls).import_txt(StringIO.StringIO(stops_csv.getvalue()),
                                  feed)