Instruction:
Make a summary of the following Python 3 code
def plot_as_routes(route_shapes, ax=None, spatial_bounds=None, map_alpha=0.8, plot_scalebar=True, legend=True,
                   return_smopy_map=False, line_width_attribute=None, line_width_scale=1.0, map_style=None):
    """
    Parameters
    ----------
    route_shapes: list of dicts that should have the following keys
            name, type, agency, lats, lons
            with types
            list, list, str, list, list
    ax: axis object
    spatial_bounds: dict
    map_alpha:
    plot_scalebar: bool
    legend:
    return_smopy_map:
    line_width_attribute:
    line_width_scale:

    Returns
    -------
    ax: matplotlib.axes object
    """
    lon_min = spatial_bounds['lon_min']
    lon_max = spatial_bounds['lon_max']
    lat_min = spatial_bounds['lat_min']
    lat_max = spatial_bounds['lat_max']
    if ax is None:
        fig = plt.figure()
        ax = fig.add_subplot(111)

    smopy_map = get_smopy_map(lon_min, lon_max, lat_min, lat_max, map_style=map_style)
    ax = smopy_map.show_mpl(figsize=None, ax=ax, alpha=map_alpha)
    bound_pixel_xs, bound_pixel_ys = smopy_map.to_pixels(numpy.array([lat_min, lat_max]),
                                                         numpy.array([lon_min, lon_max]))

    route_types_to_lines = {}
    for shape in route_shapes:
        route_type = ROUTE_TYPE_CONVERSION[shape['type']]
        lats = numpy.array(shape['lats'])
        lons = numpy.array(shape['lons'])
        if line_width_attribute:
            line_width = line_width_scale * shape[line_width_attribute]
        else:
            line_width = 1
        xs, ys = smopy_map.to_pixels(lats, lons)
        line, = ax.plot(xs, ys, linewidth=line_width, color=ROUTE_TYPE_TO_COLOR[route_type], zorder=ROUTE_TYPE_TO_ZORDER[route_type])
        route_types_to_lines[route_type] = line

    if legend:
        lines = list(route_types_to_lines.values())
        labels = [ROUTE_TYPE_TO_SHORT_DESCRIPTION[route_type] for route_type in route_types_to_lines.keys()]
        ax.legend(lines, labels, loc="upper left")

    if plot_scalebar:
        _add_scale_bar(ax, lat_max, lon_min, lon_max, bound_pixel_xs.max() - bound_pixel_xs.min())

    ax.set_xticks([])
    ax.set_yticks([])

    ax.set_xlim(bound_pixel_xs.min(), bound_pixel_xs.max())
    ax.set_ylim(bound_pixel_ys.max(), bound_pixel_ys.min())
    if return_smopy_map:
        return ax, smopy_map
    else:
        return ax

Response: Plots a route as a single line.


Instruction:
Explain what the following Python 3 code does
def _expand_spatial_bounds_to_fit_axes(bounds, ax_width, ax_height):
    b = bounds
    height_meters = util.wgs84_distance(b['lat_min'], b['lon_min'], b['lat_max'], b['lon_min'])
    width_meters = util.wgs84_distance(b['lat_min'], b['lon_min'], b['lat_min'], b['lon_max'])
    x_per_y_meters = width_meters / height_meters
    x_per_y_axes = ax_width / ax_height
    if x_per_y_axes > x_per_y_meters:  # x-axis
        # axis x_axis has slack -> the spatial longitude bounds need to be extended
        width_meters_new = (height_meters * x_per_y_axes)
        d_lon_new = ((b['lon_max'] - b['lon_min']) / width_meters) * width_meters_new
        mean_lon = (b['lon_min'] + b['lon_max'])/2.
        lon_min = mean_lon - d_lon_new / 2.
        lon_max = mean_lon + d_lon_new / 2.
        spatial_bounds = {
            "lon_min": lon_min,
            "lon_max": lon_max,
            "lat_min": b['lat_min'],
            "lat_max": b['lat_max']
        }
    else:
        # axis y_axis has slack -> the spatial latitude bounds need to be extended
        height_meters_new = (width_meters / x_per_y_axes)
        d_lat_new = ((b['lat_max'] - b['lat_min']) / height_meters) * height_meters_new
        mean_lat = (b['lat_min'] + b['lat_max']) / 2.
        lat_min = mean_lat - d_lat_new / 2.
        lat_max = mean_lat + d_lat_new / 2.
        spatial_bounds = {
            "lon_min": b['lon_min'],
            "lon_max": b['lon_max'],
            "lat_min": lat_min,
            "lat_max": lat_max
        }
    return spatial_bounds

Response: Expand the spatial bounds to fit axes.


Instruction:
Create a Python 3 function for
plotting all stops of a single object.

Response:
def plot_all_stops(g, ax=None, scalebar=False):
    """
    Parameters
    ----------
    g: A gtfspy.gtfs.GTFS object
    ax: matplotlib.Axes object, optional
        If None, a new figure and an axis is created, otherwise results are plotted on the axis.
    scalebar: bool, optional
        Whether to include a scalebar to the plot.

    Returns
    -------
    ax: matplotlib.Axes

    """
    assert(isinstance(g, GTFS))
    lon_min, lon_max, lat_min, lat_max = get_spatial_bounds(g)
    smopy_map = get_smopy_map(lon_min, lon_max, lat_min, lat_max)
    if ax is None:
        fig = plt.figure()
        ax = fig.add_subplot(111)
    ax = smopy_map.show_mpl(figsize=None, ax=ax, alpha=0.8)

    stops = g.stops()
    lats = numpy.array(stops['lat'])
    lons = numpy.array(stops['lon'])

    xs, ys = smopy_map.to_pixels(lats, lons)
    ax.scatter(xs, ys, color="red", s=10)

    ax.set_xlim(min(xs), max(xs))
    ax.set_ylim(max(ys), min(ys))
    return ax


Instruction:
Given the following Python 3 function, write the documentation
def set_process_timezone(TZ):
    try:
        prev_timezone = os.environ['TZ']
    except KeyError:
        prev_timezone = None
    os.environ['TZ'] = TZ
    time.tzset()  # Cause C-library functions to notice the update.
    return prev_timezone

Response: Sets the process timezone.


Instruction:
Make a summary of the following Python 3 code
def wgs84_distance(lat1, lon1, lat2, lon2):
    dLat = math.radians(lat2 - lat1)
    dLon = math.radians(lon2 - lon1)
    a = (math.sin(dLat / 2) * math.sin(dLat / 2) +
         math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) *
         math.sin(dLon / 2) * math.sin(dLon / 2))
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
    d = EARTH_RADIUS * c
    return d

Response: Distance between two points in WGS84 coord system.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def create_file(fname=None, fname_tmp=None, tmpdir=None,
                save_tmpfile=False, keepext=False):
    """Context manager for making files with possibility of failure.

    If you are creating a file, it is possible that the code will fail
    and leave a corrupt intermediate file.  This is especially damaging
    if this is used as automatic input to another process.  This context
    manager helps by creating a temporary filename, your code runs and
    creates that temporary file, and then if no exceptions are raised,
    the context manager will move the temporary file to the original
    filename you intended to open.

    Parameters
    ----------
    fname : str
        Target filename, this file will be created if all goes well
    fname_tmp : str
        If given, this is used as the temporary filename.
    tmpdir : str or bool
        If given, put temporary files in this directory.  If `True`,
        then find a good tmpdir that is not on local filesystem.
    save_tmpfile : bool
        If true, the temporary file is not deleteted if an exception
        is raised.
    keepext : bool, default False
            If true, have tmpfile have same extension as final file.

    Returns (as context manager value)
    ----------------------------------
     fname_tmp: str
        Temporary filename to be used.  Same as `fname_tmp`
        if given as an argument.

    Raises
    ------
    Re-raises any except occuring during the context block.
    """
    # Do nothing if requesting sqlite memory DB.
    if fname == ':memory:':
        yield fname
        return
    if fname_tmp is None:
        # no tmpfile name given - compute some basic info
        basename = os.path.basename(fname)
        root, ext = os.path.splitext(basename)
        dir_ = this_dir = os.path.dirname(fname)
        # Remove filename extension, in case this matters for
        # automatic things itself.
        if not keepext:
            root = root + ext
            ext = ''
        if tmpdir:
            # we should use a different temporary directory
            if tmpdir is True:
                # Find a directory ourself, searching some common
                # places.
                for dir__ in possible_tmpdirs:
                    if os.access(dir__, os.F_OK):
                        dir_ = dir__
                        break
        # Make the actual tmpfile, with our chosen tmpdir, directory,
        # extension.  Set it to not delete automatically, since on
        # success we will move it to elsewhere.
        tmpfile = tempfile.NamedTemporaryFile(
            prefix='tmp-' + root + '-', suffix=ext, dir=dir_, delete=False)
        fname_tmp = tmpfile.name
    try:
        yield fname_tmp
    except Exception as e:
        if save_tmpfile:
            print("Temporary file is '%s'" % fname_tmp)
        else:
            os.unlink(fname_tmp)
        raise
    # Move the file back to the original location.
    try:
        os.rename(fname_tmp, fname)
        # We have to manually set permissions.  tempfile does not use
        # umask, for obvious reasons.
        os.chmod(fname, 0o777 & ~current_umask)
    # 'Invalid cross-device link' - you can't rename files across
    # filesystems.  So, we have to fallback to moving it.  But, we
    # want to move it using tmpfiles also, so that the final file
    # appearing is atomic.  We use... tmpfiles.
    except OSError as e:
        # New temporary file in same directory
        tmpfile2 = tempfile.NamedTemporaryFile(
            prefix='tmp-' + root + '-', suffix=ext, dir=this_dir, delete=False)
        # Copy contents over
        shutil.copy(fname_tmp, tmpfile2.name)
        # Rename new tmpfile, unlink old one on other filesystem.
        os.rename(tmpfile2.name, fname)
        os.chmod(fname, 0o666 & ~current_umask)
        os.unlink(fname_tmp)

Response: Context manager for creating a new file in a context block.


Instruction:
How would you explain what the following Python 3 function does
def execute(cur, *args):
    stmt = args[0]
    if len(args) > 1:
        stmt = stmt.replace('%', '%%').replace('?', '%r')
        print(stmt % (args[1]))
    return cur.execute(*args)

Response: Utility function to print sqlite queries before executing.


Instruction:
Explain what the following Python 3 code does
def str_time_to_day_seconds(time):
    t = str(time).split(':')
    seconds = int(t[0]) * 3600 + int(t[1]) * 60 + int(t[2])
    return seconds

Response: Converts time strings to integer seconds


Instruction:
Write a Python 3 function that can
create directories if they do not exist.

Response:
def makedirs(path):
    """
    Create directories if they do not exist, otherwise do nothing.

    Return path for convenience
    """
    if not os.path.isdir(path):
        os.makedirs(path)
    return path


Instruction:
Can you tell what is the following Python 3 function doing
def source_csv_to_pandas(path, table, read_csv_args=None):
    if '.txt' not in table:
        table += '.txt'

    if isinstance(path, dict):
        data_obj = path[table]
        f = data_obj.split("\n")
    else:
        if os.path.isdir(path):
            f = open(os.path.join(path, table))

        else:

            z = zipfile.ZipFile(path)
            for path in z.namelist():
                if table in path:
                    table = path
                    break
            try:
                f = zip_open(z, table)
            except KeyError as e:
                return pd.DataFrame()

    if read_csv_args:
        df = pd.read_csv(**read_csv_args)
    else:
        df = pd.read_csv(f)
    return df

Response: Reads a CSV file and returns a pandas DataFrame.


Instruction:
Make a summary of the following Python 3 code
def write_shapefile(data, shapefile_path):
    from numpy import int64
    """
    :param data: list of dicts where dictionary contains the keys lons and lats
    :param shapefile_path: path where shapefile is saved
    :return:
    """

    w = shp.Writer(shp.POLYLINE)  # shapeType=3)

    fields = []
    encode_strings = []

    # This makes sure every geom has all the attributes
    w.autoBalance = 1
    # Create all attribute fields except for lats and lons. In addition the field names are saved for the
    # datastoring phase. Encode_strings stores .encode methods as strings for all fields that are strings
    if not fields:
        for key, value in data[0].items():
            if key != u'lats' and key != u'lons':
                fields.append(key)

                if type(value) == float:
                    w.field(key.encode('ascii'), fieldType='N', size=11, decimal=3)
                    print("float", type(value))
                elif type(value) == int or type(value) == int64:
                    print("int", type(value))

                    # encode_strings.append(".encode('ascii')")
                    w.field(key.encode('ascii'), fieldType='N', size=6, decimal=0)
                else:
                    print("other type", type(value))

                    w.field(key.encode('ascii'))

    for dict_item in data:
        line = []
        lineparts = []
        records = []
        records_string = ''
        for lat, lon in zip(dict_item[u'lats'], dict_item[u'lons']):
            line.append([float(lon), float(lat)])
        lineparts.append(line)
        w.line(parts=lineparts)

        # The shapefile records command is built up as strings to allow a differing number of columns
        for field in fields:
            if records_string:
                records_string += ", dict_item['" + field + "']"
            else:
                records_string += "dict_item['" + field + "']"
        method_string = "w.record(" + records_string + ")"

        # w.record(dict_item['name'], dict_item['agency'], dict_item['agency_name'], dict_item['type'], dict_item['lons'])
        print(method_string)
        eval(method_string)
    w.save(shapefile_path)

Response: Write a shapefile to a shapefile_path.


Instruction:
Explain what the following Python 3 code does
def draw_net_using_node_coords(net):
    import matplotlib.pyplot as plt
    fig = plt.figure()
    node_coords = {}
    for node, data in net.nodes(data=True):
        node_coords[node] = (data['lon'], data['lat'])
    ax = fig.add_subplot(111)
    networkx.draw(net, pos=node_coords, ax=ax, node_size=50)
    return fig

Response: Plot a networkx. Graph by using the lat and lon attributes of nodes.


Instruction:
Explain what the following Python 3 code does
def difference_of_pandas_dfs(df_self, df_other, col_names=None):
    df = pd.concat([df_self, df_other])
    df = df.reset_index(drop=True)
    df_gpby = df.groupby(col_names)
    idx = [x[0] for x in list(df_gpby.groups.values()) if len(x) == 1]
    df_sym_diff = df.reindex(idx)
    df_diff = pd.concat([df_other, df_sym_diff])
    df_diff = df_diff.reset_index(drop=True)
    df_gpby = df_diff.groupby(col_names)
    idx = [x[0] for x in list(df_gpby.groups.values()) if len(x) == 2]
    df_diff = df_diff.reindex(idx)
    return df_diff

Response: Returns a dataframe with all of df_self that are not in df_other when considering the columns specified in col_names.


Instruction:
Can you generate the documentation for the following Python 3 function
def _finalize_profiles(self):
        for stop, stop_profile in self._stop_profiles.items():
            assert (isinstance(stop_profile, NodeProfileMultiObjective))
            neighbor_label_bags = []
            walk_durations_to_neighbors = []
            departure_arrival_stop_pairs = []
            if stop_profile.get_walk_to_target_duration() != 0 and stop in self._walk_network.node:
                neighbors = networkx.all_neighbors(self._walk_network, stop)
                for neighbor in neighbors:
                    neighbor_profile = self._stop_profiles[neighbor]
                    assert (isinstance(neighbor_profile, NodeProfileMultiObjective))
                    neighbor_real_connection_labels = neighbor_profile.get_labels_for_real_connections()
                    neighbor_label_bags.append(neighbor_real_connection_labels)
                    walk_durations_to_neighbors.append(int(self._walk_network.get_edge_data(stop, neighbor)["d_walk"] /
                                                       self._walk_speed))
                    departure_arrival_stop_pairs.append((stop, neighbor))
            stop_profile.finalize(neighbor_label_bags, walk_durations_to_neighbors, departure_arrival_stop_pairs)

Response: Finalize the profiles of the first walks.


Instruction:
Can you write a function in Python 3 where it
imports a GTFS database into a new database.

Response:
def import_gtfs(gtfs_sources, output, preserve_connection=False,
                print_progress=True, location_name=None, **kwargs):
    """Import a GTFS database

    gtfs_sources: str, dict, list
        Paths to the gtfs zip file or to the directory containing the GTFS data.
        Alternatively, a dict can be provide that maps gtfs filenames
        (like 'stops.txt' and 'agencies.txt') to their string presentations.

    output: str or sqlite3.Connection
        path to the new database to be created, or an existing
        sqlite3 connection
    preserve_connection: bool, optional
        Whether to close the connection in the end, or not.
    print_progress: bool, optional
        Whether to print progress output
    location_name: str, optional
        set the location of this database
    """
    if isinstance(output, sqlite3.Connection):
        conn = output
    else:
        # if os.path.isfile(output):
        #  raise RuntimeError('File already exists')
        conn = sqlite3.connect(output)
    if not isinstance(gtfs_sources, list):
        gtfs_sources = [gtfs_sources]
    cur = conn.cursor()
    time_import_start = time.time()

    # These are a bit unsafe, but make importing much faster,
    # especially on scratch.
    cur.execute('PRAGMA page_size = 4096;')
    cur.execute('PRAGMA mmap_size = 1073741824;')
    cur.execute('PRAGMA cache_size = -2000000;')
    cur.execute('PRAGMA temp_store=2;')
    # Changes of isolation level are python3.6 workarounds -
    # eventually will probably be fixed and this can be removed.
    conn.isolation_level = None  # change to autocommit mode (former default)
    cur.execute('PRAGMA journal_mode = OFF;')
    #cur.execute('PRAGMA journal_mode = WAL;')
    cur.execute('PRAGMA synchronous = OFF;')
    conn.isolation_level = ''    # change back to python default.
    # end python3.6 workaround

    # Do the actual importing.
    loaders = [L(gtfssource=gtfs_sources, print_progress=print_progress, **kwargs) for L in Loaders]

    for loader in loaders:
        loader.assert_exists_if_required()

    # Do initial import.  This consists of making tables, raw insert
    # of the CSVs, and then indexing.

    for loader in loaders:
        loader.import_(conn)

    # Do any operations that require all tables present.
    for Loader in loaders:
        Loader.post_import_round2(conn)

    # Make any views
    for Loader in loaders:
        Loader.make_views(conn)

    # Make any views
    for F in postprocessors:
        F(conn)

    # Set up same basic metadata.
    from gtfspy import gtfs as mod_gtfs
    G = mod_gtfs.GTFS(output)
    G.meta['gen_time_ut'] = time.time()
    G.meta['gen_time'] = time.ctime()
    G.meta['import_seconds'] = time.time() - time_import_start
    G.meta['download_date'] = ''
    G.meta['location_name'] = ''
    G.meta['n_gtfs_sources'] = len(gtfs_sources)

    # Extract things from GTFS
    download_date_strs = []
    for i, source in enumerate(gtfs_sources):
        if len(gtfs_sources) == 1:
            prefix = ""
        else:
            prefix = "feed_" + str(i) + "_"
        if isinstance(source, string_types):
            G.meta[prefix + 'original_gtfs'] = decode_six(source) if source else None
            # Extract GTFS date.  Last date pattern in filename.
            filename_date_list = re.findall(r'\d{4}-\d{2}-\d{2}', source)
            if filename_date_list:
                date_str = filename_date_list[-1]
                G.meta[prefix + 'download_date'] = date_str
                download_date_strs.append(date_str)
            if location_name:
                G.meta['location_name'] = location_name
            else:
                location_name_list = re.findall(r'/([^/]+)/\d{4}-\d{2}-\d{2}', source)
                if location_name_list:
                    G.meta[prefix + 'location_name'] = location_name_list[-1]
                else:
                    try:
                        G.meta[prefix + 'location_name'] = source.split("/")[-4]
                    except:
                        G.meta[prefix + 'location_name'] = source

    if G.meta['download_date'] == "":
        unique_download_dates = list(set(download_date_strs))
        if len(unique_download_dates) == 1:
            G.meta['download_date'] = unique_download_dates[0]

    G.meta['timezone'] = cur.execute('SELECT timezone FROM agencies LIMIT 1').fetchone()[0]
    stats.update_stats(G)
    del G

    if print_progress:
        print("Vacuuming...")
    # Next 3 lines are python 3.6 work-arounds again.
    conn.isolation_level = None  # former default of autocommit mode
    cur.execute('VACUUM;')
    conn.isolation_level = ''    # back to python default
    # end python3.6 workaround
    if print_progress:
        print("Analyzing...")
    cur.execute('ANALYZE')
    if not (preserve_connection is True):
        conn.close()


Instruction:
How would you explain what the following Python 3 function does
def validate_day_start_ut(conn):
    G = GTFS(conn)
    cur = conn.execute('SELECT date, day_start_ut FROM days')
    for date, day_start_ut in cur:
        #print date, day_start_ut
        assert day_start_ut == G.get_day_start_ut(date)

Response: This validates the day_start_ut of the days table.


Instruction:
Explain what the following Python 3 code does
def main_make_views(gtfs_fname):
    print("creating views")
    conn = GTFS(fname_or_conn=gtfs_fname).conn
    for L in Loaders:
        L(None).make_views(conn)
    conn.commit()

Response: Re - create all views.


Instruction:
How would you implement a function in Python 3 that
checks row counts and compares them with the GTFS object

Response:
def _validate_table_row_counts(self):
        """
        Imports source .txt files, checks row counts and then compares the rowcounts with the gtfsobject
        :return:
        """
        for db_table_name in DB_TABLE_NAME_TO_SOURCE_FILE.keys():
            table_name_source_file = DB_TABLE_NAME_TO_SOURCE_FILE[db_table_name]
            row_warning_str = DB_TABLE_NAME_TO_ROWS_MISSING_WARNING[db_table_name]

            # Row count in GTFS object:
            database_row_count = self.gtfs.get_row_count(db_table_name)

            # Row counts in source files:
            source_row_count = 0
            for gtfs_source in self.gtfs_sources:
                frequencies_in_source = source_csv_to_pandas(gtfs_source, 'frequencies.txt')
                try:
                    if table_name_source_file == 'trips' and not frequencies_in_source.empty:
                        source_row_count += self._frequency_generated_trips_rows(gtfs_source)

                    elif table_name_source_file == 'stop_times' and not frequencies_in_source.empty:
                        source_row_count += self._compute_number_of_frequency_generated_stop_times(gtfs_source)
                    else:
                        df = source_csv_to_pandas(gtfs_source, table_name_source_file)

                        source_row_count += len(df.index)
                except IOError as e:
                    if hasattr(e, "filename") and db_table_name in e.filename:
                        pass
                    else:
                        raise e

            if source_row_count == database_row_count and self.verbose:
                print("Row counts match for " + table_name_source_file + " between the source and database ("
                      + str(database_row_count) + ")")
            else:
                difference = database_row_count - source_row_count
                ('Row counts do not match for ' + str(table_name_source_file) + ': (source=' + str(source_row_count) +
                      ', database=' + str(database_row_count) + ")")
                if table_name_source_file == "calendar" and difference > 0:
                    query = "SELECT count(*) FROM (SELECT * FROM calendar ORDER BY service_I DESC LIMIT " \
                            + str(int(difference)) + \
                            ") WHERE start_date=end_date AND m=0 AND t=0 AND w=0 AND th=0 AND f=0 AND s=0 AND su=0"
                    number_of_entries_added_by_calendar_dates_loader = self.gtfs.execute_custom_query(query).fetchone()[
                        0]
                    if number_of_entries_added_by_calendar_dates_loader == difference and self.verbose:
                        print("    But don't worry, the extra entries seem to just dummy entries due to calendar_dates")
                    else:
                        if self.verbose:
                            print("    Reason for this is unknown.")
                        self.warnings_container.add_warning(row_warning_str, self.location, difference)
                else:
                    self.warnings_container.add_warning(row_warning_str, self.location, difference)


Instruction:
Can you tell what is the following Python 3 function doing
def _validate_no_null_values(self):
        for table in DB_TABLE_NAMES:
            null_not_ok_warning = "Null values in must-have columns in table {table}".format(table=table)
            null_warn_warning = "Null values in good-to-have columns in table {table}".format(table=table)
            null_not_ok_fields = DB_TABLE_NAME_TO_FIELDS_WHERE_NULL_NOT_OK[table]
            null_warn_fields = DB_TABLE_NAME_TO_FIELDS_WHERE_NULL_OK_BUT_WARN[table]

            # CW, TODO: make this validation source by source
            df = self.gtfs.get_table(table)

            for warning, fields in zip([null_not_ok_warning, null_warn_warning], [null_not_ok_fields, null_warn_fields]):
                null_unwanted_df = df[fields]
                rows_having_null = null_unwanted_df.isnull().any(1)
                if sum(rows_having_null) > 0:
                    rows_having_unwanted_null = df[rows_having_null.values]
                    self.warnings_container.add_warning(warning, rows_having_unwanted_null, len(rows_having_unwanted_null))

Response: Validate that no null values are present in the database.


Instruction:
How would you explain what the following Python 3 function does
def _validate_danglers(self):
        for query, warning in zip(DANGLER_QUERIES, DANGLER_WARNINGS):
            dangler_count = self.gtfs.execute_custom_query(query).fetchone()[0]
            if dangler_count > 0:
                if self.verbose:
                    print(str(dangler_count) + " " + warning)
                self.warnings_container.add_warning(warning, self.location, count=dangler_count)

Response: Checks for rows that are not referenced in the tables that should be linked


Instruction:
Can you create a Python 3 function that
computes the number of stop times generated by the given GTFS source.

Response:
def _compute_number_of_frequency_generated_stop_times(self, gtfs_source_path):
        """
        Parameters
        ----------
        Same as for "_frequency_generated_trips_rows" but for stop times table
        gtfs_source_path:
        table_name:

        Return
        ------
        """
        df_freq = self._frequency_generated_trips_rows(gtfs_source_path, return_df_freq=True)
        df_stop_times = source_csv_to_pandas(gtfs_source_path, "stop_times")
        df_stop_freq = pd.merge(df_freq, df_stop_times, how='outer', on='trip_id')
        return int(df_stop_freq['n_trips'].fillna(1).sum(axis=0))


Instruction:
Implement a Python 3 function for
updating the set of pareto optimal tuples.

Response:
def update_pareto_optimal_tuples(self, new_label):
        """
        Parameters
        ----------
        new_label: LabelTime

        Returns
        -------
        updated: bool
        """
        assert (isinstance(new_label, LabelTime))
        if self._labels:
            assert (new_label.departure_time <= self._labels[-1].departure_time)
            best_later_departing_arrival_time = self._labels[-1].arrival_time_target
        else:
            best_later_departing_arrival_time = float('inf')

        walk_to_target_arrival_time = new_label.departure_time + self._walk_to_target_duration

        best_arrival_time = min(walk_to_target_arrival_time,
                                best_later_departing_arrival_time,
                                new_label.arrival_time_target)
        # this should be changed to get constant time insertions / additions
        # (with time-indexing)
        if (new_label.arrival_time_target < walk_to_target_arrival_time and
                new_label.arrival_time_target < best_later_departing_arrival_time):
            self._labels.append(LabelTime(new_label.departure_time, best_arrival_time))
            return True
        else:
            return False


Instruction:
Make a summary of the following Python 3 code
def print_coords(rows, prefix=''):
    lat = [row['lat'] for row in rows]
    lon = [row['lon'] for row in rows]
    print('COORDS'+'-' * 5)
    print("%slat, %slon = %r, %r" % (prefix, prefix, lat, lon))
    print('-'*5)

Response: Print the coordinates within a sequence.


Instruction:
Can you create a Python 3 function that
finds the segments between each stop and the shape point.

Response:
def find_segments(stops, shape):
    """Find corresponding shape points for a list of stops and create shape break points.

    Parameters
    ----------
    stops: stop-sequence (list)
        List of stop points
    shape: list of shape points
        shape-sequence of shape points

    Returns
    -------
    break_points: list[int]
        stops[i] corresponds to shape[break_points[i]].  This list can
        be used to partition the shape points into segments between
        one stop and the next.
    badness: float
        Lower indicates better fit to the shape.  This is the sum of
        distances (in meters) between every each stop and its closest
        shape point.  This is not needed in normal use, but in the
        cases where you must determine the best-fitting shape for a
        stop-sequence, use this.
    """
    if not shape:
        return [], 0
    break_points = []
    last_i = 0
    cumul_d = 0
    badness = 0
    d_last_stop = float('inf')
    lstlat, lstlon = None, None
    break_shape_points = []
    for stop in stops:
        stlat, stlon = stop['lat'], stop['lon']
        best_d = float('inf')
        # print stop
        if badness > 500 and badness > 30 * len(break_points):
            return [], badness
        for i in range(last_i, len(shape)):
            d = wgs84_distance(stlat, stlon, shape[i]['lat'], shape[i]['lon'])
            if lstlat:
                d_last_stop = wgs84_distance(lstlat, lstlon, shape[i]['lat'], shape[i]['lon'])
            # If we are getting closer to next stop, record this as
            # the best stop so far.continue
            if d < best_d:
                best_d = d
                best_i = i
                # print best_d, i, last_i, len(shape)
                cumul_d += d
            # We have to be very careful about our stop condition.
            # This is trial and error, basically.
            if (d_last_stop < d) or (d > 500) or (i < best_i + 100):
                    continue
            # We have decided our best stop, stop looking and continue
            # the outer loop.
            else:
                badness += best_d
                break_points.append(best_i)
                last_i = best_i
                lstlat, lstlon = stlat, stlon
                break_shape_points.append(shape[best_i])
                break
        else:
            # Executed if we did *not* break the inner loop
            badness += best_d
            break_points.append(best_i)
            last_i = best_i
            lstlat, lstlon = stlat, stlon
            break_shape_points.append(shape[best_i])
            pass
    # print "Badness:", badness
    # print_coords(stops, 'stop')
    # print_coords(shape, 'shape')
    # print_coords(break_shape_points, 'break')
    return break_points, badness


Instruction:
Can you create a Python 3 function that
finds the best shape_id for a stop - sequence.

Response:
def find_best_segments(cur, stops, shape_ids, route_id=None,
                       breakpoints_cache=None):
    """Finds the best shape_id for a stop-sequence.

    This is used in cases like when you have GPS data with a route
    name, but you don't know the route direction.  It tries shapes
    going both directions and returns the shape that best matches.
    Could be used in other cases as well.

    Parameters
    ----------
    cur : sqlite3.Cursor
        database cursor
    stops : list
    shape_ids : list of shape_id:s
    route_id : route_id to search for stops
    breakpoints_cache : dict
        If given, use this to cache results from this function.
    """
    cache_key = None
    if breakpoints_cache is not None:
        # Calculate a cache key for this sequence.  If shape_id and
        # all stop_Is are the same, then we assume that it is the same
        # route and re-use existing breakpoints.
        cache_key = (route_id, tuple(x['stop_I'] for x in stops))
        if cache_key in breakpoints_cache:
            print('found in cache')
            return breakpoints_cache[cache_key]

    if route_id is not None:
        cur.execute('''SELECT DISTINCT shape_id
                        FROM routes
                        LEFT JOIN trips
                        USING (route_I)
                        WHERE route_id=?''',
                    (route_id,))
        data = cur.fetchall()
        # If not data, then route_id didn't match anything, or there
        # were no shapes defined.  We have to exit in this case.
        if not data:
            print("No data for route_id=%s" % route_id)
            return [], None, None, None
        #
        shape_ids = zip(*data)[0]
    # print 'find_best_segments:', shape_ids
    results = []
    for shape_id in shape_ids:
        shape = get_shape_points(cur, shape_id)
        breakpoints, badness = find_segments(stops, shape)
        results.append([badness, breakpoints, shape, shape_id])
        if len(stops) > 5 and badness < 5*(len(stops)):
            break

    best = np.argmin(zip(*results)[0])
    # print 'best', best
    badness = results[best][0]
    breakpoints = results[best][1]
    shape = results[best][2]
    shape_id = results[best][3]
    if breakpoints_cache is not None:
        print("storing in cache", cache_key[0], hash(cache_key[1:]))
        breakpoints_cache[cache_key] = breakpoints, badness, shape, shape_id
    return breakpoints, badness, shape, shape_id


Instruction:
Here you have a function in Python 3, explain what it does
def return_segments(shape, break_points):
    # print 'xxx'
    # print stops
    # print shape
    # print break_points
    # assert len(stops) == len(break_points)
    segs = []
    bp = 0 # not used
    bp2 = 0
    for i in range(len(break_points)-1):
        bp = break_points[i] if break_points[i] is not None else bp2
        bp2 = break_points[i+1] if break_points[i+1] is not None else bp
        segs.append(shape[bp:bp2+1])
    segs.append([])
    return segs

Response: Break a shape into segments between stops using break_points.


Instruction:
Write a Python 3 function for
generating a cumulative distance between each stop and shape - sequence.

Response:
def gen_cumulative_distances(stops):
    """
    Add a 'd' key for distances to a stop/shape-sequence.

    This takes a shape-sequence or stop-sequence, and adds an extra
    'd' key that is cumulative, geographic distances between each
    point. This uses `wgs84_distance` from the util module.  The
    distances are in meters.  Distances are rounded to the nearest
    integer, because otherwise JSON size increases greatly.

    Parameters
    ----------
    stops: list
        elements are dicts with 'lat' and 'lon' keys
        and the function adds the 'd' key ('d' stands for distance)
        to the dictionaries
    """
    stops[0]['d'] = 0.0
    for i in range(1, len(stops)):
        stops[i]['d'] = stops[i-1]['d'] + wgs84_distance(
            stops[i-1]['lat'], stops[i-1]['lon'],
            stops[i]['lat'], stops[i]['lon'],
            )
    for stop in stops:
        stop['d'] = int(stop['d'])


Instruction:
Create a Python 3 function for
giving a shape_id return its shape - sequence.

Response:
def get_shape_points(cur, shape_id):
    """
    Given a shape_id, return its shape-sequence.

    Parameters
    ----------
    cur: sqlite3.Cursor
        cursor to a GTFS database
    shape_id: str
        id of the route

    Returns
    -------
    shape_points: list
        elements are dictionaries containing the 'seq', 'lat', and 'lon' of the shape
    """
    cur.execute('''SELECT seq, lat, lon, d FROM shapes where shape_id=?
                    ORDER BY seq''', (shape_id,))
    shape_points = [dict(seq=row[0], lat=row[1], lon=row[2], d=row[3])
                    for row in cur]
    return shape_points


Instruction:
Explain what the following Python 3 code does
def get_shape_points2(cur, shape_id):
    cur.execute('''SELECT seq, lat, lon, d FROM shapes where shape_id=?
                    ORDER BY seq''', (shape_id,))
    shape_points = {'seqs': [], 'lats':  [], 'lons': [], 'd': []}
    for row in cur:
        shape_points['seqs'].append(row[0])
        shape_points['lats'].append(row[1])
        shape_points['lons'].append(row[2])
        shape_points['d'].append(row[3])
    return shape_points

Response: Given a shape_id return its shape - sequence as a dict of lists.


Instruction:
Can you tell what is the following Python 3 function doing
def get_route_shape_segments(cur, route_id):
    cur.execute('''SELECT seq, lat, lon
                    FROM (
                        SELECT shape_id
                        FROM route
                        LEFT JOIN trips
                        USING (route_I)
                        WHERE route_id=? limit 1
                        )
                    JOIN shapes
                    USING (shape_id)
                    ORDER BY seq''', (route_id,))
    shape_points = [dict(seq=row[0], lat=row[1], lon=row[2]) for row in cur]
    return shape_points

Response: Given a route_id return its stop - sequence.


Instruction:
How would you explain what the following Python 3 function does
def get_shape_between_stops(cur, trip_I, seq_stop1=None, seq_stop2=None, shape_breaks=None):

    assert (seq_stop1 and seq_stop2) or shape_breaks
    if not shape_breaks:
        shape_breaks = []
        for seq_stop in [seq_stop1, seq_stop2]:
            query = """SELECT shape_break FROM stop_times
                        WHERE trip_I=%d AND seq=%d
                    """ % (trip_I, seq_stop)
            for row in cur.execute(query):
                shape_breaks.append(row[0])
    assert len(shape_breaks) == 2

    query = """SELECT seq, lat, lon
                FROM (SELECT shape_id FROM trips WHERE trip_I=%d)
                JOIN shapes USING (shape_id)
                WHERE seq>=%d AND seq <= %d;
            """ % (trip_I, shape_breaks[0], shape_breaks[1])
    shapedict = {'lat': [], 'lon': [], 'seq': []}
    for row in cur.execute(query):
        shapedict['seq'].append(row[0])
        shapedict['lat'].append(row[1])
        shapedict['lon'].append(row[2])
    return shapedict

Response: Given a trip_I return the shape points between two stops.


Instruction:
Create a Python 3 function for
getting all scheduled stops on a particular route_id. Given a route_id, return the trip-stop-list with latitude/longitudes. This is a bit more tricky than it seems, because we have to go from table route->trips->stop_times. This functions finds an arbitrary trip (in trip table) with this route ID and, and then returns all stop points for that trip. Parameters ---------- cur : sqlite3.Cursor cursor to sqlite3 DB containing GTFS route_id : string or any route_id to get stop points of offset : int LIMIT offset if you don't want the first trip returned. tripid_glob : string If given, allows you to limit tripids which can be selected. Mainly useful in debugging. Returns ------- stop-list List of stops in stop-seq format.

Response:
def get_trip_points(cur, route_id, offset=0, tripid_glob=''):
    """Get all scheduled stops on a particular route_id.

    Given a route_id, return the trip-stop-list with
    latitude/longitudes.  This is a bit more tricky than it seems,
    because we have to go from table route->trips->stop_times.  This
    functions finds an arbitrary trip (in trip table) with this route ID
    and, and then returns all stop points for that trip.

    Parameters
    ----------
    cur : sqlite3.Cursor
        cursor to sqlite3 DB containing GTFS
    route_id : string or any
        route_id to get stop points of
    offset : int
        LIMIT offset if you don't want the first trip returned.
    tripid_glob : string
        If given, allows you to limit tripids which can be selected.
        Mainly useful in debugging.

    Returns
    -------
    stop-list
        List of stops in stop-seq format.
    """
    extra_where = ''
    if tripid_glob:
        extra_where = "AND trip_id GLOB '%s'" % tripid_glob
    cur.execute('SELECT seq, lat, lon '
                'FROM (select trip_I from route '
                '      LEFT JOIN trips USING (route_I) '
                '      WHERE route_id=? %s limit 1 offset ? ) '
                'JOIN stop_times USING (trip_I) '
                'LEFT JOIN stop USING (stop_id) '
                'ORDER BY seq' % extra_where, (route_id, offset))
    stop_points = [dict(seq=row[0], lat=row[1], lon=row[2]) for row in cur]
    return stop_points


Instruction:
Implement a Python 3 function for
interpolating passage times for a given set of shape points.

Response:
def interpolate_shape_times(shape_distances, shape_breaks, stop_times):
    """
    Interpolate passage times for shape points.

    Parameters
    ----------
    shape_distances: list
        list of cumulative distances along the shape
    shape_breaks: list
        list of shape_breaks
    stop_times: list
        list of stop_times

    Returns
    -------
    shape_times: list of ints (seconds) / numpy array
        interpolated shape passage times

    The values of stop times before the first shape-break are given the first
    stopping time, and the any shape points after the last break point are
    given the value of the last shape point.
    """
    shape_times = np.zeros(len(shape_distances))
    shape_times[:shape_breaks[0]] = stop_times[0]
    for i in range(len(shape_breaks)-1):
        cur_break = shape_breaks[i]
        cur_time = stop_times[i]
        next_break = shape_breaks[i+1]
        next_time = stop_times[i+1]
        if cur_break == next_break:
            shape_times[cur_break] = stop_times[i]
        else:
            cur_distances = shape_distances[cur_break:next_break+1]
            norm_distances = ((np.array(cur_distances)-float(cur_distances[0])) /
                              float(cur_distances[-1] - cur_distances[0]))
            times = (1.-norm_distances)*cur_time+norm_distances*next_time
            shape_times[cur_break:next_break] = times[:-1]
    # deal final ones separately:
    shape_times[shape_breaks[-1]:] = stop_times[-1]
    return list(shape_times)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def evaluate_earliest_arrival_time_at_target(self, dep_time, transfer_margin):
        minimum = dep_time + self._walk_to_target_duration
        dep_time_plus_transfer_margin = dep_time + transfer_margin
        for label in self._labels:
            if label.departure_time >= dep_time_plus_transfer_margin and label.arrival_time_target < minimum:
                minimum = label.arrival_time_target
        return float(minimum)

Response: Evaluate the earliest arrival time at the target given a departure time and transfer margin.


Instruction:
Can you create a Python 3 function that
runs the actual simulation.

Response:
def _run(self):
        """
        Run the actual simulation.
        """
        if self._has_run:
            raise RuntimeError("This spreader instance has already been run: "
                               "create a new Spreader object for a new run.")
        i = 1
        while self.event_heap.size() > 0 and len(self._uninfected_stops) > 0:
            event = self.event_heap.pop_next_event()
            this_stop = self._stop_I_to_spreading_stop[event.from_stop_I]

            if event.arr_time_ut > self.start_time_ut + self.max_duration_ut:
                break

            if this_stop.can_infect(event):

                target_stop = self._stop_I_to_spreading_stop[event.to_stop_I]
                already_visited = target_stop.has_been_visited()
                target_stop.visit(event)

                if not already_visited:
                    self._uninfected_stops.remove(event.to_stop_I)
                    print(i, self.event_heap.size())
                    transfer_distances = self.gtfs.get_straight_line_transfer_distances(event.to_stop_I)
                    self.event_heap.add_walk_events_to_heap(transfer_distances, event, self.start_time_ut,
                                                            self.walk_speed, self._uninfected_stops,
                                                            self.max_duration_ut)
                    i += 1
        self._has_run = True


Instruction:
Create a Python 3 function to
compute the walk paths between stops and updates these to the database.

Response:
def add_walk_distances_to_db_python(gtfs, osm_path, cutoff_distance_m=1000):
    """
    Computes the walk paths between stops, and updates these to the gtfs database.

    Parameters
    ----------
    gtfs: gtfspy.GTFS or str
        A GTFS object or a string representation.
    osm_path: str
        path to the OpenStreetMap file
    cutoff_distance_m: number
        maximum allowed distance in meters

    Returns
    -------
    None

    See Also
    --------
    gtfspy.calc_transfers
    compute_walk_paths_java
    """
    if isinstance(gtfs, str):
        gtfs = GTFS(gtfs)
    assert (isinstance(gtfs, GTFS))
    print("Reading in walk network")
    walk_network = create_walk_network_from_osm(osm_path)
    print("Matching stops to the OSM network")
    stop_I_to_nearest_osm_node, stop_I_to_nearest_osm_node_distance = match_stops_to_nodes(gtfs, walk_network)

    transfers = gtfs.get_straight_line_transfer_distances()

    from_I_to_to_stop_Is = {stop_I: set() for stop_I in stop_I_to_nearest_osm_node}
    for transfer_tuple in transfers.itertuples():
        from_I = transfer_tuple.from_stop_I
        to_I = transfer_tuple.to_stop_I
        from_I_to_to_stop_Is[from_I].add(to_I)

    print("Computing walking distances")
    for from_I, to_stop_Is in from_I_to_to_stop_Is.items():
        from_node = stop_I_to_nearest_osm_node[from_I]
        from_dist = stop_I_to_nearest_osm_node_distance[from_I]
        shortest_paths = networkx.single_source_dijkstra_path_length(walk_network,
                                                                     from_node,
                                                                     cutoff=cutoff_distance_m - from_dist,
                                                                     weight="distance")
        for to_I in to_stop_Is:
            to_distance = stop_I_to_nearest_osm_node_distance[to_I]
            to_node = stop_I_to_nearest_osm_node[to_I]
            osm_distance = shortest_paths.get(to_node, float('inf'))
            total_distance = from_dist + osm_distance + to_distance
            from_stop_I_transfers = transfers[transfers['from_stop_I'] == from_I]
            straigth_distance = from_stop_I_transfers[from_stop_I_transfers["to_stop_I"] == to_I]["d"].values[0]
            assert (straigth_distance < total_distance + 2)  # allow for a maximum  of 2 meters in calculations
            if total_distance <= cutoff_distance_m:
                gtfs.conn.execute("UPDATE stop_distances "
                                  "SET d_walk = " + str(int(total_distance)) +
                                  " WHERE from_stop_I=" + str(from_I) + " AND to_stop_I=" + str(to_I))

    gtfs.conn.commit()


Instruction:
Create a Python 3 function to
match stops to nodes in a GTFS object.

Response:
def match_stops_to_nodes(gtfs, walk_network):
    """
    Parameters
    ----------
    gtfs : a GTFS object
    walk_network : networkx.Graph

    Returns
    -------
    stop_I_to_node: dict
        maps stop_I to closest walk_network node
    stop_I_to_dist: dict
        maps stop_I to the distance to the closest walk_network node
    """
    network_nodes = walk_network.nodes(data="true")

    stop_Is = set(gtfs.get_straight_line_transfer_distances()['from_stop_I'])
    stops_df = gtfs.stops()

    geo_index = GeoGridIndex(precision=6)
    for net_node, data in network_nodes:
        geo_index.add_point(GeoPoint(data['lat'], data['lon'], ref=net_node))
    stop_I_to_node = {}
    stop_I_to_dist = {}
    for stop_I in stop_Is:
        stop_lat = float(stops_df[stops_df.stop_I == stop_I].lat)
        stop_lon = float(stops_df[stops_df.stop_I == stop_I].lon)
        geo_point = GeoPoint(stop_lat, stop_lon)
        min_dist = float('inf')
        min_dist_node = None
        search_distances_m = [0.100, 0.500]
        for search_distance_m in search_distances_m:
            for point, distance in geo_index.get_nearest_points(geo_point, search_distance_m, "km"):
                if distance < min_dist:
                    min_dist = distance * 1000
                    min_dist_node = point.ref
            if min_dist_node is not None:
                break
        if min_dist_node is None:
            warn("No OSM node found for stop: " + str(stops_df[stops_df.stop_I == stop_I]))
        stop_I_to_node[stop_I] = min_dist_node
        stop_I_to_dist[stop_I] = min_dist
    return stop_I_to_node, stop_I_to_dist


Instruction:
Write a Python 3 script for
constructing the walk network for a stop transfer.

Response:
def walk_transfer_stop_to_stop_network(gtfs, max_link_distance=None):
    """
    Construct the walk network.
    If OpenStreetMap-based walking distances have been computed, then those are used as the distance.
    Otherwise, the great circle distances ("d") is used.

    Parameters
    ----------
    gtfs: gtfspy.GTFS
    max_link_distance: int, optional
        If given, all walking transfers with great circle distance longer
        than this limit (expressed in meters) will be omitted.

    Returns
    -------
    net: networkx.DiGraph
        edges have attributes
            d:
                straight-line distance between stops
            d_walk:
                distance along the road/tracks/..
    """
    if max_link_distance is None:
        max_link_distance = 1000
    net = networkx.Graph()
    _add_stops_to_net(net, gtfs.get_table("stops"))
    stop_distances = gtfs.get_table("stop_distances")
    if stop_distances["d_walk"][0] is None:
        osm_distances_available = False
        warn("Warning: OpenStreetMap-based walking distances have not been computed, using euclidean distances instead."
             "Ignore this warning if running unit tests.")
    else:
        osm_distances_available = True

    for stop_distance_tuple in stop_distances.itertuples():
        from_node = stop_distance_tuple.from_stop_I
        to_node = stop_distance_tuple.to_stop_I

        if osm_distances_available:
            if stop_distance_tuple.d_walk > max_link_distance or isnan(stop_distance_tuple.d_walk):
                continue
            data = {'d': stop_distance_tuple.d, 'd_walk': stop_distance_tuple.d_walk}
        else:
            if stop_distance_tuple.d > max_link_distance:
                continue
            data = {'d': stop_distance_tuple.d}
        net.add_edge(from_node, to_node, data)
    return net


Instruction:
Given the following Python 3 function, write the documentation
def stop_to_stop_network_for_route_type(gtfs,
                                        route_type,
                                        link_attributes=None,
                                        start_time_ut=None,
                                        end_time_ut=None):
    """
    Get a stop-to-stop network describing a single mode of travel.

    Parameters
    ----------
    gtfs : gtfspy.GTFS
    route_type : int
        See gtfspy.route_types.TRANSIT_ROUTE_TYPES for the list of possible types.
    link_attributes: list[str], optional
        defaulting to use the following link attributes:
            "n_vehicles" : Number of vehicles passed
            "duration_min" : minimum travel time between stops
            "duration_max" : maximum travel time between stops
            "duration_median" : median travel time between stops
            "duration_avg" : average travel time between stops
            "d" : distance along straight line (wgs84_distance)
            "distance_shape" : minimum distance along shape
            "capacity_estimate" : approximate capacity passed through the stop
            "route_I_counts" : dict from route_I to counts
    start_time_ut: int
        start time of the time span (in unix time)
    end_time_ut: int
        end time of the time span (in unix time)

    Returns
    -------
    net: networkx.DiGraph
        A directed graph Directed graph
    """
    if link_attributes is None:
        link_attributes = DEFAULT_STOP_TO_STOP_LINK_ATTRIBUTES
    assert(route_type in route_types.TRANSIT_ROUTE_TYPES)

    stops_dataframe = gtfs.get_stops_for_route_type(route_type)
    net = networkx.DiGraph()
    _add_stops_to_net(net, stops_dataframe)

    events_df = gtfs.get_transit_events(start_time_ut=start_time_ut,
                                        end_time_ut=end_time_ut,
                                        route_type=route_type)
    if len(net.nodes()) < 2:
        assert events_df.shape[0] == 0

    # group events by links, and loop over them (i.e. each link):
    link_event_groups = events_df.groupby(['from_stop_I', 'to_stop_I'], sort=False)
    for key, link_events in link_event_groups:
        from_stop_I, to_stop_I = key
        assert isinstance(link_events, pd.DataFrame)
        # 'dep_time_ut' 'arr_time_ut' 'shape_id' 'route_type' 'trip_I' 'duration' 'from_seq' 'to_seq'
        if link_attributes is None:
            net.add_edge(from_stop_I, to_stop_I)
        else:
            link_data = {}
            if "duration_min" in link_attributes:
                link_data['duration_min'] = float(link_events['duration'].min())
            if "duration_max" in link_attributes:
                link_data['duration_max'] = float(link_events['duration'].max())
            if "duration_median" in link_attributes:
                link_data['duration_median'] = float(link_events['duration'].median())
            if "duration_avg" in link_attributes:
                link_data['duration_avg'] = float(link_events['duration'].mean())
            # statistics on numbers of vehicles:
            if "n_vehicles" in link_attributes:
                link_data['n_vehicles'] = int(link_events.shape[0])
            if "capacity_estimate" in link_attributes:
                link_data['capacity_estimate'] = route_types.ROUTE_TYPE_TO_APPROXIMATE_CAPACITY[route_type] \
                                                 * int(link_events.shape[0])
            if "d" in link_attributes:
                from_lat = net.node[from_stop_I]['lat']
                from_lon = net.node[from_stop_I]['lon']
                to_lat = net.node[to_stop_I]['lat']
                to_lon = net.node[to_stop_I]['lon']
                distance = wgs84_distance(from_lat, from_lon, to_lat, to_lon)
                link_data['d'] = int(distance)
            if "distance_shape" in link_attributes:
                assert "shape_id" in link_events.columns.values
                found = None
                for i, shape_id in enumerate(link_events["shape_id"].values):
                    if shape_id is not None:
                        found = i
                        break
                if found is None:
                    link_data["distance_shape"] = None
                else:
                    link_event = link_events.iloc[found]
                    distance = gtfs.get_shape_distance_between_stops(
                        link_event["trip_I"],
                        int(link_event["from_seq"]),
                        int(link_event["to_seq"])
                    )
                    link_data['distance_shape'] = distance
            if "route_I_counts" in link_attributes:
                link_data["route_I_counts"] = link_events.groupby("route_I").size().to_dict()
            net.add_edge(from_stop_I, to_stop_I, attr_dict=link_data)
    return net

Response: Returns a stop - to - stop network describing a single mode of travel.


Instruction:
How would you explain what the following Python 3 function does
def stop_to_stop_networks_by_type(gtfs):
    route_type_to_network = dict()
    for route_type in route_types.ALL_ROUTE_TYPES:
        if route_type == route_types.WALK:
            net = walk_transfer_stop_to_stop_network(gtfs)
        else:
            net = stop_to_stop_network_for_route_type(gtfs, route_type)
        route_type_to_network[route_type] = net
    assert len(route_type_to_network) == len(route_types.ALL_ROUTE_TYPES)
    return route_type_to_network

Response: Compute stop - to - stop networks for all travel modes.


Instruction:
Can you generate the documentation for the following Python 3 function
def combined_stop_to_stop_transit_network(gtfs, start_time_ut=None, end_time_ut=None):
    multi_di_graph = networkx.MultiDiGraph()
    for route_type in route_types.TRANSIT_ROUTE_TYPES:
        graph = stop_to_stop_network_for_route_type(gtfs, route_type,
                                                    start_time_ut=start_time_ut, end_time_ut=end_time_ut)
        for from_node, to_node, data in graph.edges(data=True):
            data['route_type'] = route_type
        multi_di_graph.add_edges_from(graph.edges(data=True))
        multi_di_graph.add_nodes_from(graph.nodes(data=True))
    return multi_di_graph

Response: Compute stop - to - stop networks for all travel modes and combine them into a single network.


Instruction:
Write a Python 3 function that can
add nodes from the pandas dataframe describing a part of the stops table in the GTFS database.

Response:
def _add_stops_to_net(net, stops):
    """
    Add nodes to the network from the pandas dataframe describing (a part of the) stops table in the GTFS database.

    Parameters
    ----------
    net: networkx.Graph
    stops: pandas.DataFrame
    """
    for stop in stops.itertuples():
        data = {
            "lat": stop.lat,
            "lon": stop.lon,
            "name": stop.name
        }
        net.add_node(stop.stop_I, data)


Instruction:
Create a Python 3 function for
computing the temporal network of the data and return it as a pandas. DataFrame.

Response:
def temporal_network(gtfs,
                     start_time_ut=None,
                     end_time_ut=None,
                     route_type=None):
    """
    Compute the temporal network of the data, and return it as a pandas.DataFrame

    Parameters
    ----------
    gtfs : gtfspy.GTFS
    start_time_ut: int | None
        start time of the time span (in unix time)
    end_time_ut: int | None
        end time of the time span (in unix time)
    route_type: int | None
        Specifies which mode of public transport are included, or whether all modes should be included.
        The int should be one of the standard GTFS route_types:
        (see also gtfspy.route_types.TRANSIT_ROUTE_TYPES )
        If route_type is not specified, all modes are included.

    Returns
    -------
    events_df: pandas.DataFrame
        Columns: departure_stop, arrival_stop, departure_time_ut, arrival_time_ut, route_type, route_I, trip_I
    """
    events_df = gtfs.get_transit_events(start_time_ut=start_time_ut,
                                        end_time_ut=end_time_ut,
                                        route_type=route_type)
    events_df.drop('to_seq', 1, inplace=True)
    events_df.drop('shape_id', 1, inplace=True)
    events_df.drop('duration', 1, inplace=True)
    events_df.drop('route_id', 1, inplace=True)
    events_df.rename(
        columns={
            'from_seq': "seq"
        },
        inplace=True
    )
    return events_df


Instruction:
Make a summary of the following Python 3 code
def route_to_route_network(gtfs, walking_threshold, start_time, end_time):
    graph = networkx.Graph()
    routes = gtfs.get_table("routes")

    for i in routes.itertuples():
        graph.add_node(i.route_id, attr_dict={"type": i.type, "color": route_types.ROUTE_TYPE_TO_COLOR[i.type]})

    query = """SELECT stop1.route_id AS route_id1, stop1.type, stop2.route_id AS route_id2, stop2.type FROM
                (SELECT * FROM stop_distances WHERE d_walk < %s) sd,
                (SELECT * FROM stop_times, trips, routes
                WHERE stop_times.trip_I=trips.trip_I AND trips.route_I=routes.route_I
                AND stop_times.dep_time_ds > %s AND stop_times.dep_time_ds < %s) stop1,
                (SELECT * FROM stop_times, trips, routes
                WHERE stop_times.trip_I=trips.trip_I AND trips.route_I=routes.route_I
                AND stop_times.dep_time_ds > %s AND stop_times.dep_time_ds < %s) stop2
                WHERE sd.from_stop_I = stop1.stop_I AND sd.to_stop_I = stop2.stop_I AND stop1.route_id != stop2.route_id
                GROUP BY stop1.route_id, stop2.route_id""" % (walking_threshold, start_time, end_time, start_time,
                                                              end_time)
    df = gtfs.execute_custom_query_pandas(query)

    for items in df.itertuples():
        graph.add_edge(items.route_id1, items.route_id2)
    graph.remove_nodes_from(networkx.isolates(graph))
    return graph

Response: This function creates a networkx graph where the nodes are bus routes and edges are edges between the routes.


Instruction:
Can you tell what is the following Python 3 function doing
def mean_temporal_distance(self):
        total_width = self.end_time_dep - self.start_time_dep
        total_area = sum([block.area() for block in self._profile_blocks])
        return total_area / total_width

Response: Get mean temporal distance to the target.


Instruction:
Implement a function in Python 3 to
plot the temporal distance cumulative density function.

Response:
def plot_temporal_distance_cdf(self):
        """
        Plot the temporal distance cumulative density function.

        Returns
        -------
        fig: matplotlib.Figure
        """
        xvalues, cdf = self.profile_block_analyzer._temporal_distance_cdf()
        fig = plt.figure()
        ax = fig.add_subplot(111)
        xvalues = numpy.array(xvalues) / 60.0
        ax.plot(xvalues, cdf, "-k")
        ax.fill_between(xvalues, cdf, color="red", alpha=0.2)
        ax.set_ylabel("CDF(t)")
        ax.set_xlabel("Temporal distance t (min)")
        return fig


Instruction:
Write a Python 3 function for
plotting the temporal distance probability density function.

Response:
def plot_temporal_distance_pdf(self, use_minutes=True, color="green", ax=None):
        """
        Plot the temporal distance probability density function.

        Returns
        -------
        fig: matplotlib.Figure
        """
        from matplotlib import pyplot as plt
        plt.rc('text', usetex=True)
        temporal_distance_split_points_ordered, densities, delta_peaks = self._temporal_distance_pdf()
        xs = []
        for i, x in enumerate(temporal_distance_split_points_ordered):
            xs.append(x)
            xs.append(x)
        xs = numpy.array(xs)
        ys = [0]
        for y in densities:
            ys.append(y)
            ys.append(y)
        ys.append(0)
        ys = numpy.array(ys)
        # convert data to minutes:
        xlabel = "Temporal distance (s)"
        ylabel = "Probability density (t)"
        if use_minutes:
            xs /= 60.0
            ys *= 60.0
            xlabel = "Temporal distance (min)"
            delta_peaks = {peak / 60.0: mass for peak, mass in delta_peaks.items()}

        if ax is None:
            fig = plt.figure()
            ax = fig.add_subplot(111)
        ax.plot(xs, ys, "k-")
        ax.fill_between(xs, ys, color="green", alpha=0.2)

        if delta_peaks:
            peak_height = max(ys) * 1.4
            max_x = max(xs)
            min_x = min(xs)
            now_max_x = max(xs) + 0.3 * (max_x - min_x)
            now_min_x = min_x - 0.1 * (max_x - min_x)

            text_x_offset = 0.1 * (now_max_x - max_x)

            for loc, mass in delta_peaks.items():
                ax.plot([loc, loc], [0, peak_height], color="green", lw=5)
                ax.text(loc + text_x_offset, peak_height * 0.99, "$P(\\mathrm{walk}) = %.2f$" % (mass), color="green")
            ax.set_xlim(now_min_x, now_max_x)

            tot_delta_peak_mass = sum(delta_peaks.values())
            transit_text_x = (min_x + max_x) / 2
            transit_text_y = min(ys[ys > 0]) / 2.
            ax.text(transit_text_x,
                    transit_text_y,
                    "$P(mathrm{PT}) = %.2f$" % (1 - tot_delta_peak_mass),
                    color="green",
                    va="center",
                    ha="center")

        ax.set_xlabel(xlabel)
        ax.set_ylabel(ylabel)
        ax.set_ylim(bottom=0)
        return ax.figure


Instruction:
Can you implement a function in Python 3 that
plots the temporal distance probability density function.

Response:
def plot_temporal_distance_pdf_horizontal(self, use_minutes=True,
                                              color="green",
                                              ax=None,
                                              duration_divider=60.0,
                                              legend_font_size=None,
                                              legend_loc=None):
        """
        Plot the temporal distance probability density function.

        Returns
        -------
        fig: matplotlib.Figure
        """
        from matplotlib import pyplot as plt
        plt.rc('text', usetex=True)

        if ax is None:
            fig = plt.figure()
            ax = fig.add_subplot(111)

        temporal_distance_split_points_ordered, densities, delta_peaks = self._temporal_distance_pdf()
        xs = []
        for i, x in enumerate(temporal_distance_split_points_ordered):
            xs.append(x)
            xs.append(x)
        xs = numpy.array(xs)
        ys = [0]
        for y in densities:
            ys.append(y)
            ys.append(y)
        ys.append(0)
        ys = numpy.array(ys)
        # convert data to minutes:
        xlabel = "Temporal distance (s)"
        ylabel = "Probability density $P(\\tau)$"
        if use_minutes:
            xs /= duration_divider
            ys *= duration_divider
            xlabel = "Temporal distance (min)"
            delta_peaks = {peak / 60.0: mass for peak, mass in delta_peaks.items()}

        if delta_peaks:
            peak_height = max(ys) * 1.4
            max_x = max(xs)
            min_x = min(xs)
            now_max_x = max(xs) + 0.3 * (max_x - min_x)
            now_min_x = min_x - 0.1 * (max_x - min_x)

            text_x_offset = 0.1 * (now_max_x - max_x)

            for loc, mass in delta_peaks.items():
                text = "$P(\\mathrm{walk}) = " + ("%.2f$" % (mass))
                ax.plot([0, peak_height], [loc, loc], color=color, lw=5, label=text)

        ax.plot(ys, xs, "k-")
        if delta_peaks:
            tot_delta_peak_mass = sum(delta_peaks.values())
            fill_label = "$P(\\mathrm{PT}) = %.2f$" % (1-tot_delta_peak_mass)
        else:
            fill_label = None
        ax.fill_betweenx(xs, ys, color=color, alpha=0.2, label=fill_label)

        ax.set_ylabel(xlabel)
        ax.set_xlabel(ylabel)
        ax.set_xlim(left=0, right=max(ys) * 1.2)
        if delta_peaks:
            if legend_font_size is None:
                legend_font_size = 12
            if legend_loc is None:
                legend_loc = "best"
            ax.legend(loc=legend_loc, prop={'size': legend_font_size})

        if True:
            line_tyles = ["-.", "--", "-"][::-1]
            to_plot_funcs = [self.max_temporal_distance, self.mean_temporal_distance, self.min_temporal_distance]

            xmin, xmax = ax.get_xlim()
            for to_plot_func, ls in zip(to_plot_funcs, line_tyles):
                y = to_plot_func() / duration_divider
                assert y < float('inf')
                # factor of 10 just to be safe that the lines cover the whole region.
                ax.plot([xmin, xmax*10], [y, y], color="black", ls=ls, lw=1)

        return ax.figure


Instruction:
Create a Python 3 function for
plotting the temporal distance profile of the current state of the object.

Response:
def plot_temporal_distance_profile(self,
                                       timezone=None,
                                       color="black",
                                       alpha=0.15,
                                       ax=None,
                                       lw=2,
                                       label="",
                                       plot_tdist_stats=False,
                                       plot_trip_stats=False,
                                       format_string="%Y-%m-%d %H:%M:%S",
                                       plot_journeys=False,
                                       duration_divider=60.0,
                                       fill_color="green",
                                       journey_letters=None,
                                       return_letters=False):
        """
        Parameters
        ----------
        timezone: str
        color: color
        format_string: str, None
            if None, the original values are used
        plot_journeys: bool, optional
            if True, small dots are plotted at the departure times
        """
        if ax is None:
            fig = plt.figure()
            ax = fig.add_subplot(111)

        if timezone is None:
            warnings.warn("Warning: No timezone specified, defaulting to UTC")
            timezone = pytz.timezone("Etc/UTC")

        def _ut_to_unloc_datetime(ut):
            dt = datetime.datetime.fromtimestamp(ut, timezone)
            return dt.replace(tzinfo=None)

        if format_string:
            x_axis_formatter = md.DateFormatter(format_string)
            ax.xaxis.set_major_formatter(x_axis_formatter)
        else:
            _ut_to_unloc_datetime = lambda x: x

        ax.set_xlim(
            _ut_to_unloc_datetime(self.start_time_dep),
            _ut_to_unloc_datetime(self.end_time_dep)
        )

        if plot_tdist_stats:
            line_tyles = ["-.", "--", "-"][::-1]
            # to_plot_labels = ["maximum temporal distance", "mean temporal distance", "minimum temporal distance"]
            to_plot_labels  = ["$\\tau_\\mathrm{max} \\;$ = ", "$\\tau_\\mathrm{mean}$ = ", "$\\tau_\\mathrm{min} \\:\\:$ = "]
            to_plot_funcs = [self.max_temporal_distance, self.mean_temporal_distance, self.min_temporal_distance]

            xmin, xmax = ax.get_xlim()
            for to_plot_label, to_plot_func, ls in zip(to_plot_labels, to_plot_funcs, line_tyles):
                y = to_plot_func() / duration_divider
                assert y < float('inf'), to_plot_label
                to_plot_label = to_plot_label + "%.1f min" % (y)
                ax.plot([xmin, xmax], [y, y], color="black", ls=ls, lw=1, label=to_plot_label)

        if plot_trip_stats:
            assert (not plot_tdist_stats)
            line_tyles = ["-", "-.", "--"]
            to_plot_labels = ["min journey duration", "max journey duration", "mean journey duration"]
            to_plot_funcs = [self.min_trip_duration, self.max_trip_duration, self.mean_trip_duration]

            xmin, xmax = ax.get_xlim()
            for to_plot_label, to_plot_func, ls in zip(to_plot_labels, to_plot_funcs, line_tyles):
                y = to_plot_func() / duration_divider
                if not numpy.math.isnan(y):
                    ax.plot([xmin, xmax], [y, y], color="red", ls=ls, lw=2)
                    txt = to_plot_label + "\n = %.1f min" % y
                    ax.text(xmax + 0.01 * (xmax - xmin), y, txt, color="red", va="center", ha="left")

            old_xmax = xmax
            xmax += (xmax - xmin) * 0.3
            ymin, ymax = ax.get_ylim()
            ax.fill_between([old_xmax, xmax], ymin, ymax, color="gray", alpha=0.1)
            ax.set_xlim(xmin, xmax)

        # plot the actual profile
        vertical_lines, slopes = self.profile_block_analyzer.get_vlines_and_slopes_for_plotting()
        for i, line in enumerate(slopes):
            xs = [_ut_to_unloc_datetime(x) for x in line['x']]
            if i is 0:
                label = u"profile"
            else:
                label = None
            ax.plot(xs, numpy.array(line['y']) / duration_divider, "-", color=color, lw=lw, label=label)

        for line in vertical_lines:
            xs = [_ut_to_unloc_datetime(x) for x in line['x']]
            ax.plot(xs, numpy.array(line['y']) / duration_divider, ":", color=color)  # , lw=lw)

        assert (isinstance(ax, plt.Axes))

        if plot_journeys:
            xs = [_ut_to_unloc_datetime(x) for x in self.trip_departure_times]
            ys = self.trip_durations
            ax.plot(xs, numpy.array(ys) / duration_divider, "o", color="black", ms=8, label="journeys")
            if journey_letters is None:
                journey_letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

                def cycle_journey_letters(journey_letters):
                    # cycle('ABCD') --> A B C D A B C D A B C D ...
                    saved = []
                    for element in journey_letters:
                        yield element
                        saved.append(element)
                    count = 1
                    while saved:
                        for element in saved:
                            yield element + str(count)
                        count += 1
                journey_letters_iterator = cycle_journey_letters(journey_letters)
            time_letters = {int(time): letter for letter, time in zip(journey_letters_iterator, self.trip_departure_times)}
            for x, y, letter in zip(xs, ys, journey_letters_iterator):
                walking = - self._walk_time_to_target / 30 if numpy.isfinite(self._walk_time_to_target) else 0
                ax.text(x + datetime.timedelta(seconds=(self.end_time_dep - self.start_time_dep) / 60),
                        (y + walking) / duration_divider, letter, va="top", ha="left")

        fill_between_x = []
        fill_between_y = []
        for line in slopes:
            xs = [_ut_to_unloc_datetime(x) for x in line['x']]
            fill_between_x.extend(xs)
            fill_between_y.extend(numpy.array(line["y"]) / duration_divider)

        ax.fill_between(fill_between_x, y1=fill_between_y, color=fill_color, alpha=alpha, label=label)

        ax.set_ylim(bottom=0)
        ax.set_ylim(ax.get_ylim()[0], ax.get_ylim()[1] * 1.05)

        if rcParams['text.usetex']:
            ax.set_xlabel(r"Departure time $t_{\mathrm{dep}}$")
        else:
            ax.set_xlabel("Departure time")

        ax.set_ylabel(r"Temporal distance $\tau$ (min)")
        if plot_journeys and return_letters:
            return ax, time_letters
        else:
            return ax


Instruction:
Here you have a function in Python 3, explain what it does
def add_leg(self, leg):
        assert(isinstance(leg, Connection))
        if not self.legs:
            self.departure_time = leg.departure_time
        self.arrival_time = leg.arrival_time
        if leg.trip_id and (not self.legs or (leg.trip_id != self.legs[-1].trip_id)):
            self.n_boardings += 1
        self.arrival_time = leg.arrival_time
        self.legs.append(leg)

Response: Adds a new entry to the list of active legs.


Instruction:
Can you write a function in Python 3 where it
gets stop pairs through which transfers take place Returns ------- list

Response:
def get_transfer_stop_pairs(self):
        """
        Get stop pairs through which transfers take place

        Returns
        -------
        transfer_stop_pairs: list
        """
        transfer_stop_pairs = []
        previous_arrival_stop = None
        current_trip_id = None
        for leg in self.legs:
            if leg.trip_id is not None and leg.trip_id != current_trip_id and previous_arrival_stop is not None:
                transfer_stop_pair = (previous_arrival_stop, leg.departure_stop)
                transfer_stop_pairs.append(transfer_stop_pair)
            previous_arrival_stop = leg.arrival_stop
            current_trip_id = leg.trip_id
        return transfer_stop_pairs


Instruction:
Given the following Python 3 function, write the documentation
def _truncate_colormap(cmap, minval=0.0, maxval=1.0, n=100):
    new_cmap = LinearSegmentedColormap.from_list(
        'trunc({n},{a:.2f},{b:.2f})'.format(n=cmap.name, a=minval, b=maxval),
        cmap(numpy.linspace(minval, maxval, n))
    )
    return new_cmap

Response: Truncates a colormap to use.


Instruction:
Write a Python 3 script to
return a NodeProfileAnalyzerTime object for the given max_n_boardings.

Response:
def get_time_profile_analyzer(self, max_n_boardings=None):
        """
        Parameters
        ----------
        max_n_boardings: int
            The maximum number of boardings allowed for the labels used to construct the "temporal distance profile"

        Returns
        -------
        analyzer: NodeProfileAnalyzerTime
        """
        if max_n_boardings is None:
            max_n_boardings = self.max_trip_n_boardings()
        # compute only if not yet computed
        if not max_n_boardings in self._n_boardings_to_simple_time_analyzers:
            if max_n_boardings == 0:
                valids = []
            else:
                candidate_labels = [LabelTimeSimple(label.departure_time, label.arrival_time_target)
                                    for label in self._node_profile_final_labels if
                                    ((self.start_time_dep <= label.departure_time)
                                     and label.n_boardings <= max_n_boardings)]
                valids = compute_pareto_front(candidate_labels)
            valids.sort(key=lambda label: -label.departure_time)
            profile = NodeProfileSimple(self._walk_to_target_duration)
            for valid in valids:
                profile.update_pareto_optimal_tuples(valid)
            npat = NodeProfileAnalyzerTime.from_profile(profile, self.start_time_dep, self.end_time_dep)
            self._n_boardings_to_simple_time_analyzers[max_n_boardings] = npat
        return self._n_boardings_to_simple_time_analyzers[max_n_boardings]


Instruction:
Write a Python 3 script for
returning the median temporal distance of vehicle legs in the list.

Response:
def median_temporal_distances(self, min_n_boardings=None, max_n_boardings=None):
        """
        Returns
        -------
        mean_temporal_distances: list
            list indices encode the number of vehicle legs each element
            in the list tells gets the mean temporal distance
        """
        if min_n_boardings is None:
            min_n_boardings = 0

        if max_n_boardings is None:
            max_n_boardings = self.max_trip_n_boardings()
            if max_n_boardings is None:
                max_n_boardings = 0

        median_temporal_distances = [float('inf') for _ in range(min_n_boardings, max_n_boardings + 1)]
        for n_boardings in range(min_n_boardings, max_n_boardings + 1):
            simple_analyzer = self.get_time_profile_analyzer(n_boardings)
            median_temporal_distances[n_boardings] = simple_analyzer.median_temporal_distance()
        return median_temporal_distances


Instruction:
How would you explain what the following Python 3 function does
def from_directory_as_inmemory_db(cls, gtfs_directory):
        # this import is here to avoid circular imports (which turned out to be a problem)
        from gtfspy.import_gtfs import import_gtfs
        conn = sqlite3.connect(":memory:")
        import_gtfs(gtfs_directory,
                    conn,
                    preserve_connection=True,
                    print_progress=False)
        return cls(conn)

Response:
Instantiate a GTFS object by computing
            from a directory in memory.


Instruction:
Implement a function in Python 3 to
return the path to the main database

Response:
def get_main_database_path(self):
        """
        Should return the path to the database

        Returns
        -------
        path : unicode
            path to the database, empty string for in-memory databases
        """
        cur = self.conn.cursor()
        cur.execute("PRAGMA database_list")
        rows = cur.fetchall()
        for row in rows:
            if row[1] == str("main"):
                return row[2]


Instruction:
How would you implement a function in Python 3 that
gets the distance along a shape between stops.

Response:
def get_shape_distance_between_stops(self, trip_I, from_stop_seq, to_stop_seq):
        """
        Get the distance along a shape between stops

        Parameters
        ----------
        trip_I : int
            trip_ID along which we travel
        from_stop_seq : int
            the sequence number of the 'origin' stop
        to_stop_seq : int
            the sequence number of the 'destination' stop

        Returns
        -------
        distance : float, None
            If the shape calculation succeeded, return a float, otherwise return None
            (i.e. in the case where the shapes table is empty)
        """

        query_template = "SELECT shape_break FROM stop_times WHERE trip_I={trip_I} AND seq={seq} "
        stop_seqs = [from_stop_seq, to_stop_seq]
        shape_breaks = []
        for seq in stop_seqs:
            q = query_template.format(seq=seq, trip_I=trip_I)
            shape_breaks.append(self.conn.execute(q).fetchone())
        query_template = "SELECT max(d) - min(d) " \
                         "FROM shapes JOIN trips ON(trips.shape_id=shapes.shape_id) " \
                         "WHERE trip_I={trip_I} AND shapes.seq>={from_stop_seq} AND shapes.seq<={to_stop_seq};"
        distance_query = query_template.format(trip_I=trip_I, from_stop_seq=from_stop_seq, to_stop_seq=to_stop_seq)
        return self.conn.execute(distance_query).fetchone()[0]


Instruction:
Can you tell what is the following Python 3 function doing
def get_directly_accessible_stops_within_distance(self, stop, distance):
        query = """SELECT stop.* FROM
                    (SELECT st2.* FROM
                    (SELECT * FROM stop_distances
                    WHERE from_stop_I = %s) sd,
                    (SELECT * FROM stop_times) st1,
                    (SELECT * FROM stop_times) st2
                    WHERE sd.d < %s AND sd.to_stop_I = st1.stop_I AND st1.trip_I = st2.trip_I
                    GROUP BY st2.stop_I) sq,
                    (SELECT * FROM stops) stop
                    WHERE sq.stop_I = stop.stop_I""" % (stop, distance)
        return pd.read_sql_query(query, self.conn)

Response: Returns the stops that are accessible without transfer from the stops that are within a specific walking distance.


Instruction:
Create a Python 3 function for
returning the name of the GTFS timezone

Response:
def get_timezone_name(self):
        """
        Get name of the GTFS timezone

        Returns
        -------
        timezone_name : str
            name of the time zone, e.g. "Europe/Helsinki"
        """
        tz_name = self.conn.execute('SELECT timezone FROM agencies LIMIT 1').fetchone()
        if tz_name is None:
            raise ValueError("This database does not have a timezone defined.")
        return tz_name[0]


Instruction:
Can you generate the documentation for the following Python 3 function
def get_timezone_string(self, dt=None):
        if dt is None:
            download_date = self.meta.get('download_date')
            if download_date:
                dt = datetime.datetime.strptime(download_date, '%Y-%m-%d')
            else:
                dt = datetime.datetime.today()
        loc_dt = self._timezone.localize(dt)
        # get the timezone
        timezone_string = loc_dt.strftime("%z")
        return timezone_string

Response: Returns the timezone string of the GTFS database object as a string.


Instruction:
Make a summary of the following Python 3 code
def unlocalized_datetime_to_ut_seconds(self, unlocalized_datetime):
        loc_dt = self._timezone.localize(unlocalized_datetime)
        unixtime_seconds = calendar.timegm(loc_dt.utctimetuple())
        return unixtime_seconds

Response: Convert a datetime object to unixtime.


Instruction:
Explain what the following Python 3 code does
def get_day_start_ut(self, date):
        if isinstance(date, string_types):
            date = datetime.datetime.strptime(date, '%Y-%m-%d')

        date_noon = datetime.datetime(date.year, date.month, date.day, 12, 0, 0)
        ut_noon = self.unlocalized_datetime_to_ut_seconds(date_noon)
        return ut_noon - 12 * 60 * 60

Response: Get day start time as unix time in seconds


Instruction:
Create a Python 3 function for
getting all trip trajectories within a given time span.

Response:
def get_trip_trajectories_within_timespan(self, start, end, use_shapes=True, filter_name=None):
        """
        Get complete trip data for visualizing public transport operation based on gtfs.

        Parameters
        ----------
        start: number
            Earliest position data to return (in unix time)
        end: number
            Latest position data to return (in unix time)
        use_shapes: bool, optional
            Whether or not shapes should be included
        filter_name: str
            Pick only routes having this name.

        Returns
        -------
        trips: dict
            trips['trips'] is a list whose each element (e.g. el = trips['trips'][0])
            is a dict with the following properties:
                el['lats'] -- list of latitudes
                el['lons'] -- list of longitudes
                el['times'] -- list of passage_times
                el['route_type'] -- type of vehicle as specified by GTFS
                el['name'] -- name of the route
        """
        trips = []
        trip_df = self.get_tripIs_active_in_range(start, end)
        print("gtfs_viz.py: fetched " + str(len(trip_df)) + " trip ids")
        shape_cache = {}

        # loop over all trips:
        for row in trip_df.itertuples():
            trip_I = row.trip_I
            day_start_ut = row.day_start_ut
            shape_id = row.shape_id

            trip = {}

            name, route_type = self.get_route_name_and_type_of_tripI(trip_I)
            trip['route_type'] = int(route_type)
            trip['name'] = str(name)

            if filter_name and (name != filter_name):
                continue

            stop_lats = []
            stop_lons = []
            stop_dep_times = []
            shape_breaks = []
            stop_seqs = []

            # get stop_data and store it:
            stop_time_df = self.get_trip_stop_time_data(trip_I, day_start_ut)
            for stop_row in stop_time_df.itertuples():
                stop_lats.append(float(stop_row.lat))
                stop_lons.append(float(stop_row.lon))
                stop_dep_times.append(float(stop_row.dep_time_ut))
                try:
                    stop_seqs.append(int(stop_row.seq))
                except TypeError:
                    stop_seqs.append(None)
                if use_shapes:
                    try:
                        shape_breaks.append(int(stop_row.shape_break))
                    except (TypeError, ValueError):
                        shape_breaks.append(None)

            if use_shapes:
                # get shape data (from cache, if possible)
                if shape_id not in shape_cache:
                    shape_cache[shape_id] = shapes.get_shape_points2(self.conn.cursor(), shape_id)
                shape_data = shape_cache[shape_id]
                # noinspection PyBroadException
                try:
                    trip['times'] = shapes.interpolate_shape_times(shape_data['d'], shape_breaks, stop_dep_times)
                    trip['lats'] = shape_data['lats']
                    trip['lons'] = shape_data['lons']
                    start_break = shape_breaks[0]
                    end_break = shape_breaks[-1]
                    trip['times'] = trip['times'][start_break:end_break + 1]
                    trip['lats'] = trip['lats'][start_break:end_break + 1]
                    trip['lons'] = trip['lons'][start_break:end_break + 1]
                except:
                    # In case interpolation fails:
                    trip['times'] = stop_dep_times
                    trip['lats'] = stop_lats
                    trip['lons'] = stop_lons
            else:
                trip['times'] = stop_dep_times
                trip['lats'] = stop_lats
                trip['lons'] = stop_lons
            trips.append(trip)
        return {"trips": trips}


Instruction:
Here you have a function in Python 3, explain what it does
def get_stop_count_data(self, start_ut, end_ut):
        # TODO! this function could perhaps be made a single sql query now with the new tables?
        trips_df = self.get_tripIs_active_in_range(start_ut, end_ut)
        # stop_I -> count, lat, lon, name
        stop_counts = Counter()

        # loop over all trips:
        for row in trips_df.itertuples():
            # get stop_data and store it:
            stops_seq = self.get_trip_stop_time_data(row.trip_I, row.day_start_ut)
            for stop_time_row in stops_seq.itertuples(index=False):
                if (stop_time_row.dep_time_ut >= start_ut) and (stop_time_row.dep_time_ut <= end_ut):
                    stop_counts[stop_time_row.stop_I] += 1

        all_stop_data = self.stops()
        counts = [stop_counts[stop_I] for stop_I in all_stop_data["stop_I"].values]

        all_stop_data.loc[:, "count"] = pd.Series(counts, index=all_stop_data.index)
        return all_stop_data

Response: Get stop count data.


Instruction:
Explain what the following Python 3 code does
def get_segment_count_data(self, start, end, use_shapes=True):
        cur = self.conn.cursor()
        # get all possible trip_ids that take place between start and end
        trips_df = self.get_tripIs_active_in_range(start, end)
        # stop_I -> count, lat, lon, name
        segment_counts = Counter()
        seg_to_info = {}
        # tripI_to_seq = "inverted segToShapeData"
        tripI_to_seq = defaultdict(list)

        # loop over all trips:
        for row in trips_df.itertuples():
            # get stop_data and store it:
            stops_df = self.get_trip_stop_time_data(row.trip_I, row.day_start_ut)
            for i in range(len(stops_df) - 1):
                (stop_I, dep_time_ut, s_lat, s_lon, s_seq, shape_break) = stops_df.iloc[i]
                (stop_I_n, dep_time_ut_n, s_lat_n, s_lon_n, s_seq_n, shape_break_n) = stops_df.iloc[i + 1]
                # test if _contained_ in the interval
                # overlap would read:
                #   (dep_time_ut <= end) and (start <= dep_time_ut_n)
                if (dep_time_ut >= start) and (dep_time_ut_n <= end):
                    seg = (stop_I, stop_I_n)
                    segment_counts[seg] += 1
                    if seg not in seg_to_info:
                        seg_to_info[seg] = {
                            u"trip_I": row.trip_I,
                            u"lats": [s_lat, s_lat_n],
                            u"lons": [s_lon, s_lon_n],
                            u"shape_id": row.shape_id,
                            u"stop_seqs": [s_seq, s_seq_n],
                            u"shape_breaks": [shape_break, shape_break_n]
                        }
                        tripI_to_seq[row.trip_I].append(seg)

        stop_names = {}
        for (stop_I, stop_J) in segment_counts.keys():
            for s in [stop_I, stop_J]:
                if s not in stop_names:
                    stop_names[s] = self.stop(s)[u'name'].values[0]

        seg_data = []
        for seg, count in segment_counts.items():
            segInfo = seg_to_info[seg]
            shape_breaks = segInfo[u"shape_breaks"]
            seg_el = {}
            if use_shapes and shape_breaks and shape_breaks[0] and shape_breaks[1]:
                shape = shapes.get_shape_between_stops(
                    cur,
                    segInfo[u'trip_I'],
                    shape_breaks=shape_breaks
                )
                seg_el[u'lats'] = segInfo[u'lats'][:1] + shape[u'lat'] + segInfo[u'lats'][1:]
                seg_el[u'lons'] = segInfo[u'lons'][:1] + shape[u'lon'] + segInfo[u'lons'][1:]
            else:
                seg_el[u'lats'] = segInfo[u'lats']
                seg_el[u'lons'] = segInfo[u'lons']
            seg_el[u'name'] = stop_names[seg[0]] + u"-" + stop_names[seg[1]]
            seg_el[u'count'] = count
            seg_data.append(seg_el)
        return seg_data

Response: Get the count of vehicle segments that are fully contained within the interval start and end.


Instruction:
Can you create a Python 3 function that
gets the shapes of all routes.

Response:
def get_all_route_shapes(self, use_shapes=True):
        """
        Get the shapes of all routes.

        Parameters
        ----------
        use_shapes : bool, optional
            by default True (i.e. use shapes as the name of the function indicates)
            if False (fall back to lats and longitudes)

        Returns
        -------
        routeShapes: list of dicts that should have the following keys
            name, type, agency, lats, lons
            with types
            list, list, str, list, list
        """
        cur = self.conn.cursor()

        # all shape_id:s corresponding to a route_I:
        # query = "SELECT DISTINCT name, shape_id, trips.route_I, route_type
        #          FROM trips LEFT JOIN routes USING(route_I)"
        # data1 = pd.read_sql_query(query, self.conn)
        # one (arbitrary) shape_id per route_I ("one direction") -> less than half of the routes
        query = "SELECT routes.name as name, shape_id, route_I, trip_I, routes.type, " \
                "        agency_id, agencies.name as agency_name, max(end_time_ds-start_time_ds) as trip_duration " \
                "FROM trips " \
                "LEFT JOIN routes " \
                "USING(route_I) " \
                "LEFT JOIN agencies " \
                "USING(agency_I) " \
                "GROUP BY routes.route_I"
        data = pd.read_sql_query(query, self.conn)

        routeShapes = []
        for i, row in enumerate(data.itertuples()):
            datum = {"name": str(row.name), "type": int(row.type), "route_I": row.route_I, "agency": str(row.agency_id),
                     "agency_name": str(row.agency_name)}
            # this function should be made also non-shape friendly (at this point)
            if use_shapes and row.shape_id:
                shape = shapes.get_shape_points2(cur, row.shape_id)
                lats = shape['lats']
                lons = shape['lons']
            else:
                stop_shape = self.get_trip_stop_coordinates(row.trip_I)
                lats = list(stop_shape['lat'])
                lons = list(stop_shape['lon'])
            datum['lats'] = [float(lat) for lat in lats]
            datum['lons'] = [float(lon) for lon in lons]
            routeShapes.append(datum)
        return routeShapes


Instruction:
Can you implement a function in Python 3 that
gets the list of trip_IDs that are active between start and end times.

Response:
def get_tripIs_active_in_range(self, start, end):
        """
        Obtain from the (standard) GTFS database, list of trip_IDs (and other trip_related info)
        that are active between given 'start' and 'end' times.

        The start time of a trip is determined by the departure time at the last stop of the trip.
        The end time of a trip is determined by the arrival time at the last stop of the trip.

        Parameters
        ----------
        start, end : int
            the start and end of the time interval in unix time seconds

        Returns
        -------
        active_trips : pandas.DataFrame with columns
            trip_I, day_start_ut, start_time_ut, end_time_ut, shape_id
        """
        to_select = "trip_I, day_start_ut, start_time_ut, end_time_ut, shape_id "
        query = "SELECT " + to_select + \
                "FROM day_trips " \
                "WHERE " \
                "(end_time_ut > {start_ut} AND start_time_ut < {end_ut})".format(start_ut=start, end_ut=end)
        return pd.read_sql_query(query, self.conn)


Instruction:
Given the following Python 3 function, write the documentation
def get_trip_counts_per_day(self):
        query = "SELECT date, count(*) AS number_of_trips FROM day_trips GROUP BY date"
        # this yields the actual data
        trip_counts_per_day = pd.read_sql_query(query, self.conn, index_col="date")
        # the rest is simply code for filling out "gaps" in the time span
        # (necessary for some visualizations)
        max_day = trip_counts_per_day.index.max()
        min_day = trip_counts_per_day.index.min()
        min_date = datetime.datetime.strptime(min_day, '%Y-%m-%d')
        max_date = datetime.datetime.strptime(max_day, '%Y-%m-%d')
        num_days = (max_date - min_date).days
        dates = [min_date + datetime.timedelta(days=x) for x in range(num_days + 1)]
        trip_counts = []
        date_strings = []
        for date in dates:
            date_string = date.strftime("%Y-%m-%d")
            date_strings.append(date_string)
            try:
                value = trip_counts_per_day.loc[date_string, 'number_of_trips']
            except KeyError:
                # set value to 0 if dsut is not present, i.e. when no trips
                # take place on that day
                value = 0
            trip_counts.append(value)
        # check that all date_strings are included (move this to tests?)
        for date_string in trip_counts_per_day.index:
            assert date_string in date_strings
        data = {"date": dates, "date_str": date_strings, "trip_counts": trip_counts}
        return pd.DataFrame(data)

Response: Get the trip counts per day between the start and end day of the feed.