def clip(<EOL>self, array, geometries, inverted=False, clip_buffer=<NUM_LIT:0><EOL>):

return commons_clip.clip_array_with_vector(<EOL>array, self.tile.affine, geometries,<EOL>inverted=inverted, clip_buffer=clip_buffer*self.tile.pixel_x_size)<EOL>

Clip array by geometry.

Parameters
----------
array : array
    raster data to be clipped
geometries : iterable
    geometries used to clip source array
inverted : bool
    invert clipping (default: False)
clip_buffer : int
    buffer (in pixels) geometries before applying clip

Returns
-------
clipped array : array


with rasterio.Env(<EOL>**get_gdal_options(<EOL>gdal_opts,<EOL>is_remote=path_is_remote(<EOL>input_files[<NUM_LIT:0>] if isinstance(input_files, list) else input_files, s3=True<EOL>)<EOL>)<EOL>) as env:<EOL><INDENT>logger.debug("<STR_LIT>", input_files, env.options)<EOL>return _read_raster_window(<EOL>input_files,<EOL>tile,<EOL>indexes=indexes,<EOL>resampling=resampling,<EOL>src_nodata=src_nodata,<EOL>dst_nodata=dst_nodata<EOL>)<EOL><DEDENT>

Return NumPy arrays from an input raster.

NumPy arrays are reprojected and resampled to tile properties from input
raster. If tile boundaries cross the antimeridian, data on the other side
of the antimeridian will be read and concatenated to the numpy array
accordingly.

Parameters
----------
input_files : string or list
    path to a raster file or list of paths to multiple raster files readable by
    rasterio.
tile : Tile
    a Tile object
indexes : list or int
    a list of band numbers; None will read all.
resampling : string
    one of "nearest", "average", "bilinear" or "lanczos"
src_nodata : int or float, optional
    if not set, the nodata value from the source dataset will be used
dst_nodata : int or float, optional
    if not set, the nodata value from the source dataset will be used
gdal_opts : dict
    GDAL options passed on to rasterio.Env()

Returns
-------
raster : MaskedArray


Extract a numpy array from a raster file.


def read_raster_no_crs(input_file, indexes=None, gdal_opts=None):

with warnings.catch_warnings():<EOL><INDENT>warnings.simplefilter("<STR_LIT:ignore>")<EOL>try:<EOL><INDENT>with rasterio.Env(<EOL>**get_gdal_options(<EOL>gdal_opts, is_remote=path_is_remote(input_file, s3=True)<EOL>)<EOL>):<EOL><INDENT>with rasterio.open(input_file, "<STR_LIT:r>") as src:<EOL><INDENT>return src.read(indexes=indexes, masked=True)<EOL><DEDENT><DEDENT><DEDENT>except RasterioIOError as e:<EOL><INDENT>for i in ("<STR_LIT>", "<STR_LIT>"):<EOL><INDENT>if i in str(e):<EOL><INDENT>raise FileNotFoundError("<STR_LIT>" % input_file)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>raise<EOL><DEDENT><DEDENT><DEDENT>

Wrapper function around rasterio.open().read().

Parameters
----------
input_file : str
    Path to file
indexes : int or list
    Band index or list of band indexes to be read.

Returns
-------
MaskedArray

Raises
------
FileNotFoundError if file cannot be found.


def write_raster_window(<EOL>in_tile=None, in_data=None, out_profile=None, out_tile=None, out_path=None,<EOL>tags=None, bucket_resource=None<EOL>):

if not isinstance(out_path, str):<EOL><INDENT>raise TypeError("<STR_LIT>")<EOL><DEDENT>logger.debug("<STR_LIT>", out_path)<EOL>if out_path == "<STR_LIT>":<EOL><INDENT>raise DeprecationWarning(<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>)<EOL><DEDENT>out_tile = in_tile if out_tile is None else out_tile<EOL>_validate_write_window_params(in_tile, out_tile, in_data, out_profile)<EOL>window_data = extract_from_array(<EOL>in_raster=in_data,<EOL>in_affine=in_tile.affine,<EOL>out_tile=out_tile<EOL>) if in_tile != out_tile else in_data<EOL>if "<STR_LIT>" in out_profile:<EOL><INDENT>out_profile["<STR_LIT>"] = out_profile.pop("<STR_LIT>")<EOL><DEDENT>if window_data.all() is not ma.masked:<EOL><INDENT>try:<EOL><INDENT>if out_path.startswith("<STR_LIT>"):<EOL><INDENT>with RasterWindowMemoryFile(<EOL>in_tile=out_tile,<EOL>in_data=window_data,<EOL>out_profile=out_profile,<EOL>out_tile=out_tile,<EOL>tags=tags<EOL>) as memfile:<EOL><INDENT>logger.debug((out_tile.id, "<STR_LIT>", out_path))<EOL>bucket_resource.put_object(<EOL>Key="<STR_LIT:/>".join(out_path.split("<STR_LIT:/>")[<NUM_LIT:3>:]),<EOL>Body=memfile<EOL>)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>with rasterio.open(out_path, '<STR_LIT:w>', **out_profile) as dst:<EOL><INDENT>logger.debug((out_tile.id, "<STR_LIT>", out_path))<EOL>dst.write(window_data.astype(out_profile["<STR_LIT>"], copy=False))<EOL>_write_tags(dst, tags)<EOL><DEDENT><DEDENT><DEDENT>except Exception as e:<EOL><INDENT>logger.exception("<STR_LIT>", out_path, e)<EOL>raise<EOL><DEDENT><DEDENT>else:<EOL><INDENT>logger.debug((out_tile.id, "<STR_LIT>", out_path))<EOL><DEDENT>

Write a window from a numpy array to an output file.

Parameters
----------
in_tile : ``BufferedTile``
    ``BufferedTile`` with a data attribute holding NumPy data
in_data : array
out_profile : dictionary
    metadata dictionary for rasterio
out_tile : ``Tile``
    provides output boundaries; if None, in_tile is used
out_path : string
    output path to write to
tags : optional tags to be added to GeoTIFF file
bucket_resource : boto3 bucket resource to write to in case of S3 output


def extract_from_array(in_raster=None, in_affine=None, out_tile=None):

if isinstance(in_raster, ReferencedRaster):<EOL><INDENT>in_affine = in_raster.affine<EOL>in_raster = in_raster.data<EOL><DEDENT>minrow, maxrow, mincol, maxcol = bounds_to_ranges(<EOL>out_bounds=out_tile.bounds, in_affine=in_affine, in_shape=in_raster.shape<EOL>)<EOL>if (<EOL>minrow >= <NUM_LIT:0> and<EOL>mincol >= <NUM_LIT:0> and<EOL>maxrow <= in_raster.shape[-<NUM_LIT:2>] and<EOL>maxcol <= in_raster.shape[-<NUM_LIT:1>]<EOL>):<EOL><INDENT>return in_raster[..., minrow:maxrow, mincol:maxcol]<EOL><DEDENT>else:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>

Extract raster data window array.

Parameters
----------
in_raster : array or ReferencedRaster
in_affine : ``Affine`` required if in_raster is an array
out_tile : ``BufferedTile``

Returns
-------
extracted array : array


<EOL>if isinstance(in_raster, ma.MaskedArray):<EOL><INDENT>pass<EOL><DEDENT>if isinstance(in_raster, np.ndarray):<EOL><INDENT>in_raster = ma.MaskedArray(in_raster, mask=in_raster == nodataval)<EOL><DEDENT>elif isinstance(in_raster, ReferencedRaster):<EOL><INDENT>in_affine = in_raster.affine<EOL>in_crs = in_raster.crs<EOL>in_raster = in_raster.data<EOL><DEDENT>elif isinstance(in_raster, tuple):<EOL><INDENT>in_raster = ma.MaskedArray(<EOL>data=np.stack(in_raster),<EOL>mask=np.stack([<EOL>band.mask<EOL>if isinstance(band, ma.masked_array)<EOL>else np.where(band == nodataval, True, False)<EOL>for band in in_raster<EOL>]),<EOL>fill_value=nodataval<EOL>)<EOL><DEDENT>else:<EOL><INDENT>raise TypeError("<STR_LIT>" % type(in_raster))<EOL><DEDENT>if in_raster.ndim == <NUM_LIT:2>:<EOL><INDENT>in_raster = ma.expand_dims(in_raster, axis=<NUM_LIT:0>)<EOL><DEDENT>elif in_raster.ndim == <NUM_LIT:3>:<EOL><INDENT>pass<EOL><DEDENT>else:<EOL><INDENT>raise TypeError("<STR_LIT>")<EOL><DEDENT>if in_raster.fill_value != nodataval:<EOL><INDENT>ma.set_fill_value(in_raster, nodataval)<EOL><DEDENT>out_shape = (in_raster.shape[<NUM_LIT:0>], ) + out_tile.shape<EOL>dst_data = np.empty(out_shape, in_raster.dtype)<EOL>in_raster = ma.masked_array(<EOL>data=in_raster.filled(), mask=in_raster.mask, fill_value=nodataval<EOL>)<EOL>reproject(<EOL>in_raster,<EOL>dst_data,<EOL>src_transform=in_affine,<EOL>src_crs=in_crs if in_crs else out_tile.crs,<EOL>dst_transform=out_tile.affine,<EOL>dst_crs=out_tile.crs,<EOL>resampling=Resampling[resampling]<EOL>)<EOL>return ma.MaskedArray(dst_data, mask=dst_data == nodataval)<EOL>

Extract and resample from array to target tile.

Parameters
----------
in_raster : array
in_affine : ``Affine``
out_tile : ``BufferedTile``
resampling : string
    one of rasterio's resampling methods (default: nearest)
nodataval : integer or float
    raster nodata value (default: 0)

Returns
-------
resampled array : array


if isinstance(tiles, GeneratorType):<EOL><INDENT>tiles = list(tiles)<EOL><DEDENT>elif not isinstance(tiles, list):<EOL><INDENT>raise TypeError("<STR_LIT>")<EOL><DEDENT>if not all([isinstance(pair, tuple) for pair in tiles]):<EOL><INDENT>raise TypeError("<STR_LIT>")<EOL><DEDENT>if not all([<EOL>all([isinstance(tile, BufferedTile), isinstance(data, np.ndarray)])<EOL>for tile, data in tiles<EOL>]):<EOL><INDENT>raise TypeError("<STR_LIT>")<EOL><DEDENT>if len(tiles) == <NUM_LIT:0>:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>logger.debug("<STR_LIT>", len(tiles))<EOL>if len(tiles) == <NUM_LIT:1>:<EOL><INDENT>tile, data = tiles[<NUM_LIT:0>]<EOL>return ReferencedRaster(<EOL>data=data,<EOL>affine=tile.affine,<EOL>bounds=tile.bounds,<EOL>crs=tile.crs<EOL>)<EOL><DEDENT>pyramid, resolution, dtype = _get_tiles_properties(tiles)<EOL>shift = _shift_required(tiles)<EOL>m_left, m_bottom, m_right, m_top = None, None, None, None<EOL>for tile, data in tiles:<EOL><INDENT>num_bands = data.shape[<NUM_LIT:0>] if data.ndim > <NUM_LIT:2> else <NUM_LIT:1><EOL>left, bottom, right, top = tile.bounds<EOL>if shift:<EOL><INDENT>left += pyramid.x_size / <NUM_LIT:2><EOL>right += pyramid.x_size / <NUM_LIT:2><EOL>if right > pyramid.right:<EOL><INDENT>right -= pyramid.x_size<EOL>left -= pyramid.x_size<EOL><DEDENT><DEDENT>m_left = min([left, m_left]) if m_left is not None else left<EOL>m_bottom = min([bottom, m_bottom]) if m_bottom is not None else bottom<EOL>m_right = max([right, m_right]) if m_right is not None else right<EOL>m_top = max([top, m_top]) if m_top is not None else top<EOL><DEDENT>height = int(round((m_top - m_bottom) / resolution))<EOL>width = int(round((m_right - m_left) / resolution))<EOL>mosaic = ma.MaskedArray(<EOL>data=np.full((num_bands, height, width), dtype=dtype, fill_value=nodata),<EOL>mask=np.ones((num_bands, height, width))<EOL>)<EOL>affine = Affine(resolution, <NUM_LIT:0>, m_left, <NUM_LIT:0>, -resolution, m_top)<EOL>for tile, data in tiles:<EOL><INDENT>data = prepare_array(data, nodata=nodata, dtype=dtype)<EOL>t_left, t_bottom, t_right, t_top = tile.bounds<EOL>if shift:<EOL><INDENT>t_left += pyramid.x_size / <NUM_LIT:2><EOL>t_right += pyramid.x_size / <NUM_LIT:2><EOL>if t_right > pyramid.right:<EOL><INDENT>t_right -= pyramid.x_size<EOL>t_left -= pyramid.x_size<EOL><DEDENT><DEDENT>minrow, maxrow, mincol, maxcol = bounds_to_ranges(<EOL>out_bounds=(t_left, t_bottom, t_right, t_top),<EOL>in_affine=affine,<EOL>in_shape=(height, width)<EOL>)<EOL>mosaic[:, minrow:maxrow, mincol:maxcol] = data<EOL>mosaic.mask[:, minrow:maxrow, mincol:maxcol] = data.mask<EOL><DEDENT>if shift:<EOL><INDENT>affine = Affine(resolution, <NUM_LIT:0>, m_left - pyramid.x_size / <NUM_LIT:2>, <NUM_LIT:0>, -resolution, m_top)<EOL><DEDENT>return ReferencedRaster(<EOL>data=mosaic,<EOL>affine=affine,<EOL>bounds=Bounds(m_left, m_bottom, m_right, m_top),<EOL>crs=tile.crs<EOL>)<EOL>

Create a mosaic from tiles. Tiles must be connected (also possible over Antimeridian),
otherwise strange things can happen!

Parameters
----------
tiles : iterable
    an iterable containing tuples of a BufferedTile and an array
nodata : integer or float
    raster nodata value to initialize the mosaic with (default: 0)

Returns
-------
mosaic : ReferencedRaster


def bounds_to_ranges(out_bounds=None, in_affine=None, in_shape=None):

Return bounds range values from geolocated input.

Parameters
----------
out_bounds : tuple
    left, bottom, right, top
in_affine : Affine
    input geolocation
in_shape : tuple
    input shape

Returns
-------
minrow, maxrow, mincol, maxcol


if not tiles:<EOL><INDENT>raise TypeError("<STR_LIT>")<EOL><DEDENT>pixel_size = tiles[<NUM_LIT:0>].pixel_x_size<EOL>left, bottom, right, top = (<EOL>min([t.left for t in tiles]),<EOL>min([t.bottom for t in tiles]),<EOL>max([t.right for t in tiles]),<EOL>max([t.top for t in tiles]),<EOL>)<EOL>return (<EOL>Affine(pixel_size, <NUM_LIT:0>, left, <NUM_LIT:0>, -pixel_size, top),<EOL>Shape(<EOL>width=int(round((right - left) / pixel_size, <NUM_LIT:0>)),<EOL>height=int(round((top - bottom) / pixel_size, <NUM_LIT:0>)),<EOL>)<EOL>)<EOL>

Return Affine and shape of combined tiles.

Parameters
----------
tiles : iterable
    an iterable containing BufferedTiles

Returns
-------
Affine, Shape


if tiles[<NUM_LIT:0>][<NUM_LIT:0>].tile_pyramid.is_global:<EOL><INDENT>tile_cols = sorted(list(set([t[<NUM_LIT:0>].col for t in tiles])))<EOL>if tile_cols == list(range(min(tile_cols), max(tile_cols) + <NUM_LIT:1>)):<EOL><INDENT>return False<EOL><DEDENT>else:<EOL><INDENT>def gen_groups(items):<EOL><INDENT>"""<STR_LIT>"""<EOL>j = items[<NUM_LIT:0>]<EOL>group = [j]<EOL>for i in items[<NUM_LIT:1>:]:<EOL><INDENT>if i == j + <NUM_LIT:1>:<EOL><INDENT>group.append(i)<EOL><DEDENT>else:<EOL><INDENT>yield group<EOL>group = [i]<EOL><DEDENT>j = i<EOL><DEDENT>yield group<EOL><DEDENT>groups = list(gen_groups(tile_cols))<EOL>if len(groups) == <NUM_LIT:1>:<EOL><INDENT>return False<EOL><DEDENT>normal_distance = groups[-<NUM_LIT:1>][-<NUM_LIT:1>] - groups[<NUM_LIT:0>][<NUM_LIT:0>]<EOL>antimeridian_distance = (<EOL>groups[<NUM_LIT:0>][-<NUM_LIT:1>] + tiles[<NUM_LIT:0>][<NUM_LIT:0>].tile_pyramid.matrix_width(tiles[<NUM_LIT:0>][<NUM_LIT:0>].zoom)<EOL>) - groups[-<NUM_LIT:1>][<NUM_LIT:0>]<EOL>return antimeridian_distance < normal_distance<EOL><DEDENT><DEDENT>else:<EOL><INDENT>return False<EOL><DEDENT>

Determine if distance over antimeridian is shorter than normal distance.


memfile = MemoryFile()<EOL>profile.update(width=data.shape[-<NUM_LIT:2>], height=data.shape[-<NUM_LIT:1>])<EOL>with memfile.open(**profile) as dataset:<EOL><INDENT>dataset.write(data)<EOL><DEDENT>return memfile<EOL>

Return a rasterio.io.MemoryFile instance from input.

Parameters
----------
data : array
    array to be written
profile : dict
    rasterio profile for MemoryFile


def prepare_array(data, masked=True, nodata=<NUM_LIT:0>, dtype="<STR_LIT>"):

<EOL>if isinstance(data, (list, tuple)):<EOL><INDENT>return _prepare_iterable(data, masked, nodata, dtype)<EOL><DEDENT>elif isinstance(data, np.ndarray) and data.ndim == <NUM_LIT:2>:<EOL><INDENT>data = ma.expand_dims(data, axis=<NUM_LIT:0>)<EOL><DEDENT>if isinstance(data, ma.MaskedArray):<EOL><INDENT>return _prepare_masked(data, masked, nodata, dtype)<EOL><DEDENT>elif isinstance(data, np.ndarray):<EOL><INDENT>if masked:<EOL><INDENT>return ma.masked_values(data.astype(dtype, copy=False), nodata, copy=False)<EOL><DEDENT>else:<EOL><INDENT>return data.astype(dtype, copy=False)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>raise ValueError(<EOL>"<STR_LIT>"<EOL>)<EOL><DEDENT>

Turn input data into a proper array for further usage.

Outut array is always 3-dimensional with the given data type. If the output
is masked, the fill_value corresponds to the given nodata value and the
nodata value will be burned into the data array.

Parameters
----------
data : array or iterable
    array (masked or normal) or iterable containing arrays
nodata : integer or float
    nodata value (default: 0) used if input is not a masked array and
    for output array
masked : bool
    return a NumPy Array or a NumPy MaskedArray (default: True)
dtype : string
    data type of output array (default: "int16")

Returns
-------
array : array


def __init__(<EOL>self, in_tile=None, in_data=None, out_profile=None, out_tile=None, tags=None<EOL>):

out_tile = in_tile if out_tile is None else out_tile<EOL>_validate_write_window_params(in_tile, out_tile, in_data, out_profile)<EOL>self.data = extract_from_array(<EOL>in_raster=in_data,<EOL>in_affine=in_tile.affine,<EOL>out_tile=out_tile<EOL>)<EOL>if "<STR_LIT>" in out_profile:<EOL><INDENT>out_profile["<STR_LIT>"] = out_profile.pop("<STR_LIT>")<EOL><DEDENT>self.profile = out_profile<EOL>self.tags = tags<EOL>


self.rio_memfile = MemoryFile()<EOL>with self.rio_memfile.open(**self.profile) as dst:<EOL><INDENT>dst.write(self.data.astype(self.profile["<STR_LIT>"], copy=False))<EOL>_write_tags(dst, self.tags)<EOL><DEDENT>return self.rio_memfile<EOL>


tile_pyramid = BufferedTilePyramid(tile_pyramid_type)<EOL>with rasterio.open(input_file, "<STR_LIT:r>") as src:<EOL><INDENT>xmin, ymin, xmax, ymax = reproject_geometry(<EOL>segmentize_geometry(<EOL>box(<EOL>src.bounds.left, src.bounds.bottom, src.bounds.right,<EOL>src.bounds.top<EOL>),<EOL>get_segmentize_value(input_file, tile_pyramid)<EOL>),<EOL>src_crs=src.crs, dst_crs=tile_pyramid.crs<EOL>).bounds<EOL>x_dif = xmax - xmin<EOL>y_dif = ymax - ymin<EOL>size = float(src.width + src.height)<EOL>avg_resolution = (<EOL>(x_dif / float(src.width)) * (float(src.width) / size) +<EOL>(y_dif / float(src.height)) * (float(src.height) / size)<EOL>)<EOL><DEDENT>for zoom in range(<NUM_LIT:0>, <NUM_LIT>):<EOL><INDENT>if tile_pyramid.pixel_x_size(zoom) <= avg_resolution:<EOL><INDENT>return zoom-<NUM_LIT:1><EOL><DEDENT><DEDENT>

Determine the best base zoom level for a raster.

"Best" means the maximum zoom level where no oversampling has to be done.

Parameters
----------
input_file : path to raster file
tile_pyramid_type : ``TilePyramid`` projection (``geodetic`` or``mercator``)

Returns
-------
zoom : integer


with rasterio.open(input_file, "<STR_LIT:r>") as input_raster:<EOL><INDENT>pixelsize = input_raster.transform[<NUM_LIT:0>]<EOL><DEDENT>return pixelsize * tile_pyramid.tile_size<EOL>

Return the recommended segmentation value in input file units.

It is calculated by multiplyling raster pixel size with tile shape in
pixels.

Parameters
----------
input_file : str
    location of a file readable by rasterio
tile_pyramied : ``TilePyramid`` or ``BufferedTilePyramid``
    tile pyramid to estimate target tile size

Returns
-------
segmenize value : float
    length suggested of line segmentation to reproject file bounds


def tile_to_zoom_level(tile, dst_pyramid=None, matching_method="<STR_LIT>", precision=<NUM_LIT:8>):

def width_height(bounds):<EOL><INDENT>try:<EOL><INDENT>l, b, r, t = reproject_geometry(<EOL>box(*bounds), src_crs=tile.crs, dst_crs=dst_pyramid.crs<EOL>).bounds<EOL><DEDENT>except ValueError:<EOL><INDENT>raise TopologicalError("<STR_LIT>")<EOL><DEDENT>return r - l, t - b<EOL><DEDENT>if tile.tp.crs == dst_pyramid.crs:<EOL><INDENT>return tile.zoom<EOL><DEDENT>else:<EOL><INDENT>if matching_method == "<STR_LIT>":<EOL><INDENT>transform, width, height = calculate_default_transform(<EOL>tile.tp.crs,<EOL>dst_pyramid.crs,<EOL>tile.width,<EOL>tile.height,<EOL>*tile.bounds<EOL>)<EOL>tile_resolution = round(transform[<NUM_LIT:0>], precision)<EOL><DEDENT>elif matching_method == "<STR_LIT>":<EOL><INDENT>l, b, r, t = tile.bounds<EOL>x = tile.pixel_x_size<EOL>y = tile.pixel_y_size<EOL>res = []<EOL>for bounds in [<EOL>(l, t - y, l + x, t),  <EOL>(l, b, l + x, b + y),  <EOL>(r - x, b, r, b + y),  <EOL>(r - x, t - y, r, t)   <EOL>]:<EOL><INDENT>try:<EOL><INDENT>w, h = width_height(bounds)<EOL>res.extend([w, h])<EOL><DEDENT>except TopologicalError:<EOL><INDENT>logger.debug("<STR_LIT>")<EOL><DEDENT><DEDENT>if res:<EOL><INDENT>tile_resolution = round(min(res), precision)<EOL><DEDENT>else:<EOL><INDENT>raise TopologicalError("<STR_LIT>")<EOL><DEDENT><DEDENT>else:<EOL><INDENT>raise ValueError("<STR_LIT>", matching_method)<EOL><DEDENT>logger.debug(<EOL>"<STR_LIT>",<EOL>tile_resolution<EOL>)<EOL>zoom = <NUM_LIT:0><EOL>while True:<EOL><INDENT>td_resolution = round(dst_pyramid.pixel_x_size(zoom), precision)<EOL>if td_resolution <= tile_resolution:<EOL><INDENT>break<EOL><DEDENT>zoom += <NUM_LIT:1><EOL><DEDENT>logger.debug("<STR_LIT>", tile_resolution, zoom, td_resolution)<EOL>return zoom<EOL><DEDENT>

Determine the best zoom level in target TilePyramid from given Tile.

Parameters
----------
tile : BufferedTile
dst_pyramid : BufferedTilePyramid
matching_method : str ('gdal' or 'min')
    gdal: Uses GDAL's standard method. Here, the target resolution is calculated by
        averaging the extent's pixel sizes over both x and y axes. This approach
        returns a zoom level which may not have the best quality but will speed up
        reading significantly.
    min: Returns the zoom level which matches the minimum resolution of the extent's
        four corner pixels. This approach returns the zoom level with the best
        possible quality but with low performance. If the tile extent is outside of
        the destination pyramid, a TopologicalError will be raised.
precision : int
    Round resolutions to n digits before comparing.

Returns
-------
zoom : int


prefixes = ("<STR_LIT>", "<STR_LIT>", "<STR_LIT>")<EOL>if s3:<EOL><INDENT>prefixes += ("<STR_LIT>", "<STR_LIT>")<EOL><DEDENT>return path.startswith(prefixes)<EOL>

Determine whether file path is remote or local.

Parameters
----------
path : path to file

Returns
-------
is_remote : bool


if path.startswith(("<STR_LIT>", "<STR_LIT>")):<EOL><INDENT>try:<EOL><INDENT>urlopen(path).info()<EOL>return True<EOL><DEDENT>except HTTPError as e:<EOL><INDENT>if e.code == <NUM_LIT>:<EOL><INDENT>return False<EOL><DEDENT>else:<EOL><INDENT>raise<EOL><DEDENT><DEDENT><DEDENT>elif path.startswith("<STR_LIT>"):<EOL><INDENT>bucket = get_boto3_bucket(path.split("<STR_LIT:/>")[<NUM_LIT:2>])<EOL>key = "<STR_LIT:/>".join(path.split("<STR_LIT:/>")[<NUM_LIT:3>:])<EOL>for obj in bucket.objects.filter(Prefix=key):<EOL><INDENT>if obj.key == key:<EOL><INDENT>return True<EOL><DEDENT><DEDENT>else:<EOL><INDENT>return False<EOL><DEDENT><DEDENT>else:<EOL><INDENT>logger.debug("<STR_LIT>", path, os.path.exists(path))<EOL>return os.path.exists(path)<EOL><DEDENT>

Check if file exists either remote or local.

Parameters:
-----------
path : path to file

Returns:
--------
exists : bool


if path_is_remote(path):<EOL><INDENT>return path<EOL><DEDENT>else:<EOL><INDENT>if os.path.isabs(path):<EOL><INDENT>return path<EOL><DEDENT>else:<EOL><INDENT>if base_dir is None or not os.path.isabs(base_dir):<EOL><INDENT>raise TypeError("<STR_LIT>")<EOL><DEDENT>return os.path.abspath(os.path.join(base_dir, path))<EOL><DEDENT><DEDENT>

Return absolute path if path is local.

Parameters:
-----------
path : path to file
base_dir : base directory used for absolute path

Returns:
--------
absolute path


if path_is_remote(path) or not os.path.isabs(path):<EOL><INDENT>return path<EOL><DEDENT>else:<EOL><INDENT>return os.path.relpath(path, base_dir)<EOL><DEDENT>

Return relative path if path is local.

Parameters:
-----------
path : path to file
base_dir : directory where path sould be relative to

Returns:
--------
relative path


if not path_is_remote(path):<EOL><INDENT>try:<EOL><INDENT>os.makedirs(path)<EOL><DEDENT>except OSError:<EOL><INDENT>pass<EOL><DEDENT><DEDENT>

Silently create all subdirectories of path if path is local.

Parameters:
-----------
path : path


logger.debug("<STR_LIT>", params, path)<EOL>if path.startswith("<STR_LIT>"):<EOL><INDENT>bucket = get_boto3_bucket(path.split("<STR_LIT:/>")[<NUM_LIT:2>])<EOL>key = "<STR_LIT:/>".join(path.split("<STR_LIT:/>")[<NUM_LIT:3>:])<EOL>logger.debug("<STR_LIT>", key)<EOL>bucket.put_object(<EOL>Key=key,<EOL>Body=json.dumps(params, sort_keys=True, indent=<NUM_LIT:4>)<EOL>)<EOL><DEDENT>else:<EOL><INDENT>makedirs(os.path.dirname(path))<EOL>with open(path, '<STR_LIT:w>') as dst:<EOL><INDENT>json.dump(params, dst, sort_keys=True, indent=<NUM_LIT:4>)<EOL><DEDENT><DEDENT>


if path.startswith(("<STR_LIT>", "<STR_LIT>")):<EOL><INDENT>try:<EOL><INDENT>return json.loads(urlopen(path).read().decode())<EOL><DEDENT>except HTTPError:<EOL><INDENT>raise FileNotFoundError("<STR_LIT>", path)<EOL><DEDENT><DEDENT>elif path.startswith("<STR_LIT>"):<EOL><INDENT>bucket = get_boto3_bucket(path.split("<STR_LIT:/>")[<NUM_LIT:2>])<EOL>key = "<STR_LIT:/>".join(path.split("<STR_LIT:/>")[<NUM_LIT:3>:])<EOL>for obj in bucket.objects.filter(Prefix=key):<EOL><INDENT>if obj.key == key:<EOL><INDENT>return json.loads(obj.get()['<STR_LIT>'].read().decode())<EOL><DEDENT><DEDENT>raise FileNotFoundError("<STR_LIT>", path)<EOL><DEDENT>else:<EOL><INDENT>try:<EOL><INDENT>with open(path, "<STR_LIT:r>") as src:<EOL><INDENT>return json.loads(src.read())<EOL><DEDENT><DEDENT>except:<EOL><INDENT>raise FileNotFoundError("<STR_LIT>", path)<EOL><DEDENT><DEDENT>


user_opts = {} if opts is None else dict(**opts)<EOL>if is_remote:<EOL><INDENT>return dict(GDAL_HTTP_OPTS, **user_opts)<EOL><DEDENT>else:<EOL><INDENT>return user_opts<EOL><DEDENT>

Return a merged set of custom and default GDAL/rasterio Env options.

If is_remote is set to True, the default GDAL_HTTP_OPTS are appended.

Parameters
----------
opts : dict or None
    Explicit GDAL options.
is_remote : bool
    Indicate whether Env is for a remote file.

Returns
-------
dictionary


def reproject_geometry(<EOL>geometry, src_crs=None, dst_crs=None, error_on_clip=False, validity_check=True,<EOL>antimeridian_cutting=False<EOL>):

src_crs = _validated_crs(src_crs)<EOL>dst_crs = _validated_crs(dst_crs)<EOL>def _reproject_geom(geometry, src_crs, dst_crs):<EOL><INDENT>if geometry.is_empty:<EOL><INDENT>return geometry<EOL><DEDENT>else:<EOL><INDENT>out_geom = to_shape(<EOL>transform_geom(<EOL>src_crs.to_dict(),<EOL>dst_crs.to_dict(),<EOL>mapping(geometry),<EOL>antimeridian_cutting=antimeridian_cutting<EOL>)<EOL>)<EOL>return _repair(out_geom) if validity_check else out_geom<EOL><DEDENT><DEDENT>if src_crs == dst_crs or geometry.is_empty:<EOL><INDENT>return _repair(geometry)<EOL><DEDENT>elif (<EOL>dst_crs.is_epsg_code and               <EOL>dst_crs.get("<STR_LIT>") in CRS_BOUNDS and  <EOL>dst_crs.get("<STR_LIT>") != "<STR_LIT>"     <EOL>):<EOL><INDENT>wgs84_crs = CRS().from_epsg(<NUM_LIT>)<EOL>crs_bbox = box(*CRS_BOUNDS[dst_crs.get("<STR_LIT>")])<EOL>geometry_4326 = _reproject_geom(geometry, src_crs, wgs84_crs)<EOL>if error_on_clip and not geometry_4326.within(crs_bbox):<EOL><INDENT>raise RuntimeError("<STR_LIT>")<EOL><DEDENT>return _reproject_geom(crs_bbox.intersection(geometry_4326), wgs84_crs, dst_crs)<EOL><DEDENT>else:<EOL><INDENT>return _reproject_geom(geometry, src_crs, dst_crs)<EOL><DEDENT>

Reproject a geometry to target CRS.

Also, clips geometry if it lies outside the destination CRS boundary.
Supported destination CRSes for clipping: 4326 (WGS84), 3857 (Spherical
Mercator) and 3035 (ETRS89 / ETRS-LAEA).

Parameters
----------
geometry : ``shapely.geometry``
src_crs : ``rasterio.crs.CRS`` or EPSG code
    CRS of source data
dst_crs : ``rasterio.crs.CRS`` or EPSG code
    target CRS
error_on_clip : bool
    raises a ``RuntimeError`` if a geometry is outside of CRS bounds
    (default: False)
validity_check : bool
    checks if reprojected geometry is valid and throws ``TopologicalError``
    if invalid (default: True)
antimeridian_cutting : bool
    cut geometry at Antimeridian; can result in a multipart output geometry

Returns
-------
geometry : ``shapely.geometry``


if geometry.geom_type != "<STR_LIT>":<EOL><INDENT>raise TypeError("<STR_LIT>")<EOL><DEDENT>return Polygon(<EOL>LinearRing([<EOL>p<EOL>for l in map(<EOL>lambda x: LineString([x[<NUM_LIT:0>], x[<NUM_LIT:1>]]),<EOL>zip(geometry.exterior.coords[:-<NUM_LIT:1>], geometry.exterior.coords[<NUM_LIT:1>:])<EOL>)<EOL>for p in [<EOL>l.interpolate(segmentize_value * i).coords[<NUM_LIT:0>]<EOL>for i in range(int(l.length / segmentize_value))<EOL>] + [l.coords[<NUM_LIT:1>]]<EOL>])<EOL>)<EOL>

Segmentize Polygon outer ring by segmentize value.

Just Polygon geometry type supported.

Parameters
----------
geometry : ``shapely.geometry``
segmentize_value: float

Returns
-------
geometry : ``shapely.geometry``


def read_vector_window(input_files, tile, validity_check=True):

if not isinstance(input_files, list):<EOL><INDENT>input_files = [input_files]<EOL><DEDENT>return [<EOL>feature<EOL>for feature in chain.from_iterable([<EOL>_read_vector_window(path, tile, validity_check=validity_check)<EOL>for path in input_files<EOL>])<EOL>]<EOL>

Read a window of an input vector dataset.

Also clips geometry.

Parameters:
-----------
input_file : string
    path to vector file
tile : ``Tile``
    tile extent to read data from
validity_check : bool
    checks if reprojected geometry is valid and throws ``RuntimeError`` if
    invalid (default: True)

Returns
-------
features : list
  a list of reprojected GeoJSON-like features


def write_vector_window(<EOL>in_data=None, out_schema=None, out_tile=None, out_path=None, bucket_resource=None<EOL>):

<EOL>try:<EOL><INDENT>os.remove(out_path)<EOL><DEDENT>except OSError:<EOL><INDENT>pass<EOL><DEDENT>out_features = []<EOL>for feature in in_data:<EOL><INDENT>try:<EOL><INDENT>for out_geom in multipart_to_singleparts(<EOL>clean_geometry_type(<EOL>to_shape(feature["<STR_LIT>"]).intersection(out_tile.bbox),<EOL>out_schema["<STR_LIT>"]<EOL>)<EOL>):<EOL><INDENT>out_features.append({<EOL>"<STR_LIT>": mapping(out_geom),<EOL>"<STR_LIT>": feature["<STR_LIT>"]<EOL>})<EOL><DEDENT><DEDENT>except Exception as e:<EOL><INDENT>logger.warning("<STR_LIT>", e)<EOL>continue<EOL><DEDENT><DEDENT>if out_features:<EOL><INDENT>try:<EOL><INDENT>if out_path.startswith("<STR_LIT>"):<EOL><INDENT>with VectorWindowMemoryFile(<EOL>tile=out_tile,<EOL>features=out_features,<EOL>schema=out_schema,<EOL>driver="<STR_LIT>"<EOL>) as memfile:<EOL><INDENT>logger.debug((out_tile.id, "<STR_LIT>", out_path))<EOL>bucket_resource.put_object(<EOL>Key="<STR_LIT:/>".join(out_path.split("<STR_LIT:/>")[<NUM_LIT:3>:]),<EOL>Body=memfile<EOL>)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>with fiona.open(<EOL>out_path, '<STR_LIT:w>', schema=out_schema, driver="<STR_LIT>",<EOL>crs=out_tile.crs.to_dict()<EOL>) as dst:<EOL><INDENT>logger.debug((out_tile.id, "<STR_LIT>", out_path))<EOL>dst.writerecords(out_features)<EOL><DEDENT><DEDENT><DEDENT>except Exception as e:<EOL><INDENT>logger.error("<STR_LIT>", out_path, e)<EOL>raise<EOL><DEDENT><DEDENT>else:<EOL><INDENT>logger.debug((out_tile.id, "<STR_LIT>", out_path))<EOL><DEDENT>

Write features to GeoJSON file.

Parameters
----------
in_data : features
out_schema : dictionary
    output schema for fiona
out_tile : ``BufferedTile``
    tile used for output extent
out_path : string
    output path for GeoJSON file


def clean_geometry_type(geometry, target_type, allow_multipart=True):

multipart_geoms = {<EOL>"<STR_LIT>": MultiPoint,<EOL>"<STR_LIT>": MultiLineString,<EOL>"<STR_LIT>": MultiPolygon,<EOL>"<STR_LIT>": MultiPoint,<EOL>"<STR_LIT>": MultiLineString,<EOL>"<STR_LIT>": MultiPolygon<EOL>}<EOL>if target_type not in multipart_geoms.keys():<EOL><INDENT>raise TypeError("<STR_LIT>" % target_type)<EOL><DEDENT>if geometry.geom_type == target_type:<EOL><INDENT>return geometry<EOL><DEDENT>elif allow_multipart:<EOL><INDENT>target_multipart_type = multipart_geoms[target_type]<EOL>if geometry.geom_type == "<STR_LIT>":<EOL><INDENT>return target_multipart_type([<EOL>clean_geometry_type(g, target_type, allow_multipart)<EOL>for g in geometry])<EOL><DEDENT>elif any([<EOL>isinstance(geometry, target_multipart_type),<EOL>multipart_geoms[geometry.geom_type] == target_multipart_type<EOL>]):<EOL><INDENT>return geometry<EOL><DEDENT><DEDENT>raise GeometryTypeError(<EOL>"<STR_LIT>" % (geometry.geom_type, target_type)<EOL>)<EOL>

Return geometry of a specific type if possible.

Filters and splits up GeometryCollection into target types. This is
necessary when after clipping and/or reprojecting the geometry types from
source geometries change (i.e. a Polygon becomes a LineString or a
LineString becomes Point) in some edge cases.

Parameters
----------
geometry : ``shapely.geometry``
target_type : string
    target geometry type
allow_multipart : bool
    allow multipart geometries (default: True)

Returns
-------
cleaned geometry : ``shapely.geometry``
    returns None if input geometry type differs from target type

Raises
------
GeometryTypeError : if geometry type does not match target_type


return shape(geom) if isinstance(geom, dict) else geom<EOL>

Convert geometry to shapely geometry if necessary.

Parameters:
-----------
geom : shapely geometry or GeoJSON mapping

Returns:
--------
shapely geometry


if isinstance(geom, base.BaseGeometry):<EOL><INDENT>if hasattr(geom, "<STR_LIT>"):<EOL><INDENT>for subgeom in geom:<EOL><INDENT>yield subgeom<EOL><DEDENT><DEDENT>else:<EOL><INDENT>yield geom<EOL><DEDENT><DEDENT>

Yield single part geometries if geom is multipart, otherwise yield geom.

Parameters:
-----------
geom : shapely geometry

Returns:
--------
shapely single part geometries


def __init__(<EOL>self, tile=None, features=None, schema=None, driver=None<EOL>):

self.tile = tile<EOL>self.schema = schema<EOL>self.driver = driver<EOL>self.features = features<EOL>


self.fio_memfile = MemoryFile()<EOL>with self.fio_memfile.open(<EOL>schema=self.schema,<EOL>driver=self.driver,<EOL>crs=self.tile.crs<EOL>) as dst:<EOL><INDENT>dst.writerecords(self.features)<EOL><DEDENT>return self.fio_memfile<EOL>


for zoom in get_zoom_levels(process_zoom_levels=zoom):<EOL><INDENT>with ExitStack() as es:<EOL><INDENT>index_writers = []<EOL>if geojson:<EOL><INDENT>index_writers.append(<EOL>es.enter_context(<EOL>VectorFileWriter(<EOL>driver="<STR_LIT>",<EOL>out_path=_index_file_path(out_dir, zoom, "<STR_LIT>"),<EOL>crs=mp.config.output_pyramid.crs,<EOL>fieldname=fieldname<EOL>)<EOL>)<EOL>)<EOL><DEDENT>if gpkg:<EOL><INDENT>index_writers.append(<EOL>es.enter_context(<EOL>VectorFileWriter(<EOL>driver="<STR_LIT>",<EOL>out_path=_index_file_path(out_dir, zoom, "<STR_LIT>"),<EOL>crs=mp.config.output_pyramid.crs,<EOL>fieldname=fieldname<EOL>)<EOL>)<EOL>)<EOL><DEDENT>if shapefile:<EOL><INDENT>index_writers.append(<EOL>es.enter_context(<EOL>VectorFileWriter(<EOL>driver="<STR_LIT>",<EOL>out_path=_index_file_path(out_dir, zoom, "<STR_LIT>"),<EOL>crs=mp.config.output_pyramid.crs,<EOL>fieldname=fieldname<EOL>)<EOL>)<EOL>)<EOL><DEDENT>if txt:<EOL><INDENT>index_writers.append(<EOL>es.enter_context(<EOL>TextFileWriter(out_path=_index_file_path(out_dir, zoom, "<STR_LIT>"))<EOL>)<EOL>)<EOL><DEDENT>if vrt:<EOL><INDENT>index_writers.append(<EOL>es.enter_context(<EOL>VRTFileWriter(<EOL>out_path=_index_file_path(out_dir, zoom, "<STR_LIT>"),<EOL>output=mp.config.output,<EOL>out_pyramid=mp.config.output_pyramid<EOL>)<EOL>)<EOL>)<EOL><DEDENT>logger.debug("<STR_LIT>", index_writers)<EOL>def _worker(tile):<EOL><INDENT>tile_path = _tile_path(<EOL>orig_path=mp.config.output.get_path(tile),<EOL>basepath=basepath,<EOL>for_gdal=for_gdal<EOL>)<EOL>indexes = [<EOL>i for i in index_writers<EOL>if not i.entry_exists(tile=tile, path=tile_path)<EOL>]<EOL>if indexes:<EOL><INDENT>output_exists = mp.config.output.tiles_exist(output_tile=tile)<EOL><DEDENT>else:<EOL><INDENT>output_exists = None<EOL><DEDENT>return tile, tile_path, indexes, output_exists<EOL><DEDENT>with concurrent.futures.ThreadPoolExecutor() as executor:<EOL><INDENT>for task in concurrent.futures.as_completed(<EOL>(<EOL>executor.submit(_worker, i)<EOL>for i in mp.config.output_pyramid.tiles_from_geom(<EOL>mp.config.area_at_zoom(zoom), zoom<EOL>)<EOL>)<EOL>):<EOL><INDENT>tile, tile_path, indexes, output_exists = task.result()<EOL>if indexes and output_exists:<EOL><INDENT>logger.debug("<STR_LIT>", tile_path)<EOL>logger.debug("<STR_LIT>" % len(indexes))<EOL>for index in indexes:<EOL><INDENT>index.write(tile, tile_path)<EOL><DEDENT><DEDENT>yield tile<EOL><DEDENT><DEDENT><DEDENT><DEDENT>

Generate indexes for given zoom level.

Parameters
----------
mp : Mapchete object
    process output to be indexed
out_dir : path
    optionally override process output directory
zoom : int
    zoom level to be processed
geojson : bool
    generate GeoJSON index (default: False)
gpkg : bool
    generate GeoPackage index (default: False)
shapefile : bool
    generate Shapefile index (default: False)
txt : bool
    generate tile path list textfile (default: False)
vrt : bool
    GDAL-style VRT file (default: False)
fieldname : str
    field name which contains paths of tiles (default: "location")
basepath : str
    if set, use custom base path instead of output path
for_gdal : bool
    use GDAL compatible remote paths, i.e. add "/vsicurl/" before path
    (default: True)


def __init__(<EOL>self, grid=None, metatiling=<NUM_LIT:1>, tile_size=<NUM_LIT>, pixelbuffer=<NUM_LIT:0><EOL>):

TilePyramid.__init__(self, grid, metatiling=metatiling, tile_size=tile_size)<EOL>self.tile_pyramid = TilePyramid(grid, metatiling=metatiling, tile_size=tile_size)<EOL>self.metatiling = metatiling<EOL>if isinstance(pixelbuffer, int) and pixelbuffer >= <NUM_LIT:0>:<EOL><INDENT>self.pixelbuffer = pixelbuffer<EOL><DEDENT>else:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>


tile = self.tile_pyramid.tile(zoom, row, col)<EOL>return BufferedTile(tile, pixelbuffer=self.pixelbuffer)<EOL>

Return ``BufferedTile`` object of this ``BufferedTilePyramid``.

Parameters
----------
zoom : integer
    zoom level
row : integer
    tile matrix row
col : integer
    tile matrix column

Returns
-------
buffered tile : ``BufferedTile``


def tiles_from_bounds(self, bounds, zoom):

for tile in self.tiles_from_bbox(box(*bounds), zoom):<EOL><INDENT>yield self.tile(*tile.id)<EOL><DEDENT>

Return all tiles intersecting with bounds.

Bounds values will be cleaned if they cross the antimeridian or are
outside of the Northern or Southern tile pyramid bounds.

Parameters
----------
bounds : tuple
    (left, bottom, right, top) bounding values in tile pyramid CRS
zoom : integer
    zoom level

Yields
------
intersecting tiles : generator
    generates ``BufferedTiles``


def tiles_from_bbox(self, geometry, zoom):

for tile in self.tile_pyramid.tiles_from_bbox(geometry, zoom):<EOL><INDENT>yield self.tile(*tile.id)<EOL><DEDENT>

All metatiles intersecting with given bounding box.

Parameters
----------
geometry : ``shapely.geometry``
zoom : integer
    zoom level

Yields
------
intersecting tiles : generator
    generates ``BufferedTiles``


def tiles_from_geom(self, geometry, zoom):

for tile in self.tile_pyramid.tiles_from_geom(geometry, zoom):<EOL><INDENT>yield self.tile(*tile.id)<EOL><DEDENT>

Return all tiles intersecting with input geometry.

Parameters
----------
geometry : ``shapely.geometry``
zoom : integer
    zoom level

Yields
------
intersecting tiles : ``BufferedTile``


return [<EOL>self.tile(*intersecting_tile.id)<EOL>for intersecting_tile in self.tile_pyramid.intersecting(tile)<EOL>]<EOL>

Return all BufferedTiles intersecting with tile.

Parameters
----------
tile : ``BufferedTile``
    another tile


return dict(<EOL>grid=self.grid.to_dict(),<EOL>metatiling=self.metatiling,<EOL>tile_size=self.tile_size,<EOL>pixelbuffer=self.pixelbuffer<EOL>)<EOL>

Return dictionary representation of pyramid parameters.


return BufferedTilePyramid(**config_dict)<EOL>

Initialize TilePyramid from configuration dictionary.


def __init__(self, tile, pixelbuffer=<NUM_LIT:0>):

assert not isinstance(tile, BufferedTile)<EOL>Tile.__init__(self, tile.tile_pyramid, tile.zoom, tile.row, tile.col)<EOL>self._tile = tile<EOL>self.pixelbuffer = pixelbuffer<EOL>


return self._tile.shape(pixelbuffer=self.pixelbuffer).height<EOL>


return self._tile.shape(pixelbuffer=self.pixelbuffer).width<EOL>


return self._tile.shape(pixelbuffer=self.pixelbuffer)<EOL>


return self._tile.affine(pixelbuffer=self.pixelbuffer)<EOL>


return self._tile.bounds(pixelbuffer=self.pixelbuffer)<EOL>


return self._tile.bbox(pixelbuffer=self.pixelbuffer)<EOL>


return [BufferedTile(t, self.pixelbuffer) for t in self._tile.get_children()]<EOL>

Get tile children (intersecting tiles in next zoom level).

Returns
-------
children : list
    a list of ``BufferedTiles``


return BufferedTile(self._tile.get_parent(), self.pixelbuffer)<EOL>

Get tile parent (intersecting tile in previous zoom level).

Returns
-------
parent : ``BufferedTile``


return [<EOL>BufferedTile(t, self.pixelbuffer)<EOL>for t in self._tile.get_neighbors(connectedness=connectedness)<EOL>]<EOL>

Return tile neighbors.

Tile neighbors are unique, i.e. in some edge cases, where both the left
and right neighbor wrapped around the antimeridian is the same. Also,
neighbors ouside the northern and southern TilePyramid boundaries are
excluded, because they are invalid.

-------------
| 8 | 1 | 5 |
-------------
| 4 | x | 2 |
-------------
| 7 | 3 | 6 |
-------------

Parameters
----------
connectedness : int
    [4 or 8] return four direct neighbors or all eight.

Returns
-------
list of BufferedTiles


return (<EOL>self.left <= self.tile_pyramid.left or      <EOL>self.bottom <= self.tile_pyramid.bottom or  <EOL>self.right >= self.tile_pyramid.right or    <EOL>self.top >= self.tile_pyramid.top           <EOL>)<EOL>

Determine whether tile touches or goes over pyramid edge.


warnings.warn(<EOL>DeprecationWarning(<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>)<EOL>)<EOL>return logging.getLogger("<STR_LIT>" + pname)<EOL>

Logger to be used within a user process file.


warnings.warn(<EOL>DeprecationWarning(<EOL>"<STR_LIT>"<EOL>)<EOL>)<EOL>return logging.getLogger("<STR_LIT>" + dname)<EOL>


<EOL>if "<STR_LIT>" in mp.params["<STR_LIT:input>"]:<EOL><INDENT>clip_geom = mp.open("<STR_LIT>").read()<EOL>if not clip_geom:<EOL><INDENT>logger.debug("<STR_LIT>")<EOL>return "<STR_LIT>"<EOL><DEDENT><DEDENT>else:<EOL><INDENT>clip_geom = []<EOL><DEDENT>with mp.open(<EOL>"<STR_LIT>",<EOL>matching_method=td_matching_method,<EOL>matching_max_zoom=td_matching_max_zoom,<EOL>matching_precision=td_matching_precision,<EOL>fallback_to_higher_zoom=td_fallback_to_higher_zoom,<EOL>resampling=td_resampling<EOL>) as raster:<EOL><INDENT>raster_data = raster.read()<EOL>if raster.is_empty() or raster_data[<NUM_LIT:0>].mask.all():<EOL><INDENT>logger.debug("<STR_LIT>")<EOL>return "<STR_LIT>"<EOL><DEDENT><DEDENT>if clip_geom:<EOL><INDENT>clipped = mp.clip(<EOL>np.where(raster_data[<NUM_LIT:0>].mask, mp.params["<STR_LIT>"].nodata, raster_data),<EOL>clip_geom,<EOL>clip_buffer=clip_pixelbuffer,<EOL>inverted=True<EOL>)<EOL>return np.where(clipped.mask, clipped, mp.params["<STR_LIT>"].nodata)<EOL><DEDENT>else:<EOL><INDENT>return np.where(raster_data[<NUM_LIT:0>].mask, mp.params["<STR_LIT>"].nodata, raster_data)<EOL><DEDENT>

Convert and optionally clip input raster data.

Inputs:
-------
raster
    singleband or multiband data input
clip (optional)
    vector data used to clip output

Parameters
----------
td_resampling : str (default: 'nearest')
    Resampling used when reading from TileDirectory.
td_matching_method : str ('gdal' or 'min') (default: 'gdal')
    gdal: Uses GDAL's standard method. Here, the target resolution is
        calculated by averaging the extent's pixel sizes over both x and y
        axes. This approach returns a zoom level which may not have the
        best quality but will speed up reading significantly.
    min: Returns the zoom level which matches the minimum resolution of the
        extents four corner pixels. This approach returns the zoom level
        with the best possible quality but with low performance. If the
        tile extent is outside of the destination pyramid, a
        TopologicalError will be raised.
td_matching_max_zoom : int (optional, default: None)
    If set, it will prevent reading from zoom levels above the maximum.
td_matching_precision : int (default: 8)
    Round resolutions to n digits before comparing.
td_fallback_to_higher_zoom : bool (default: False)
    In case no data is found at zoom level, try to read data from higher
    zoom levels. Enabling this setting can lead to many IO requests in
    areas with no data.
clip_pixelbuffer : int
    Use pixelbuffer when clipping output by geometry. (default: 0)

Output
------
np.ndarray


with mp.open("<STR_LIT>", resampling=resampling) as raster_file:<EOL><INDENT>if raster_file.is_empty():<EOL><INDENT>return "<STR_LIT>"<EOL><DEDENT>scaled = ()<EOL>mask = ()<EOL>raster_data = raster_file.read()<EOL>if raster_data.ndim == <NUM_LIT:2>:<EOL><INDENT>raster_data = ma.expand_dims(raster_data, axis=<NUM_LIT:0>)<EOL><DEDENT>if not scale_method:<EOL><INDENT>scales_minmax = [(i, i) for i in range(len(raster_data))]<EOL><DEDENT>for band, (scale_min, scale_max) in zip(raster_data, scales_minmax):<EOL><INDENT>if scale_method in ["<STR_LIT>", "<STR_LIT>"]:<EOL><INDENT>scaled += (_stretch_array(band, scale_min, scale_max), )<EOL><DEDENT>elif scale_method == "<STR_LIT>":<EOL><INDENT>scaled += (np.clip(band, scale_min, scale_max), )<EOL><DEDENT>else:<EOL><INDENT>scaled += (band, )<EOL><DEDENT>mask += (band.mask, )<EOL><DEDENT><DEDENT>return ma.masked_array(np.stack(scaled), np.stack(mask))<EOL>

Read, stretch and return raster data.

Inputs:
-------
raster
    raster file

Parameters:
-----------
resampling : str
    rasterio.Resampling method
scale_method : str
    - dtype_scale: use dtype minimum and maximum values
    - minmax_scale: use dataset bands minimum and maximum values
    - crop: clip data to output dtype
scales_minmax : tuple
    tuple of band specific scale values

Output:
-------
np.ndarray


<EOL>with mp.open("<STR_LIT>", resampling="<STR_LIT>") as raster_file:<EOL><INDENT>if raster_file.is_empty():<EOL><INDENT>return "<STR_LIT>"<EOL><DEDENT>dem = raster_file.read()<EOL><DEDENT>return dem<EOL>

Example process for testing.

Inputs:
-------
file1
    raster file

Parameters:
-----------

Output:
-------
np.ndarray


if os.path.isfile(process_file) or os.path.isfile(mapchete_file):<EOL><INDENT>if not force:<EOL><INDENT>raise IOError("<STR_LIT>")<EOL><DEDENT><DEDENT>out_path = out_path if out_path else os.path.join(os.getcwd(), "<STR_LIT>")<EOL>process_template = pkg_resources.resource_filename(<EOL>"<STR_LIT>", "<STR_LIT>"<EOL>)<EOL>process_file = os.path.join(os.getcwd(), process_file)<EOL>copyfile(process_template, process_file)<EOL>mapchete_template = pkg_resources.resource_filename(<EOL>"<STR_LIT>", "<STR_LIT>"<EOL>)<EOL>output_options = dict(<EOL>format=out_format, path=out_path, **FORMAT_MANDATORY[out_format]<EOL>)<EOL>pyramid_options = {'<STR_LIT>': pyramid_type}<EOL>substitute_elements = {<EOL>'<STR_LIT>': process_file,<EOL>'<STR_LIT>': dump({'<STR_LIT>': output_options}, default_flow_style=False),<EOL>'<STR_LIT>': dump({'<STR_LIT>': pyramid_options}, default_flow_style=False)<EOL>}<EOL>with open(mapchete_template, '<STR_LIT:r>') as config_template:<EOL><INDENT>config = Template(config_template.read())<EOL>customized_config = config.substitute(substitute_elements)<EOL><DEDENT>with open(mapchete_file, '<STR_LIT:w>') as target_config:<EOL><INDENT>target_config.write(customized_config)<EOL><DEDENT>

Create an empty Mapchete and process file in a given directory.


multi = multi if multi else cpu_count()<EOL>mode = "<STR_LIT>" if overwrite else "<STR_LIT>"<EOL>if debug or not verbose:<EOL><INDENT>verbose_dst = open(os.devnull, '<STR_LIT:w>')<EOL><DEDENT>else:<EOL><INDENT>verbose_dst = sys.stdout<EOL><DEDENT>for mapchete_file in mapchete_files:<EOL><INDENT>tqdm.tqdm.write("<STR_LIT>" % mapchete_file, file=verbose_dst)<EOL>with click_spinner.spinner(disable=debug) as spinner:<EOL><INDENT>if tile:<EOL><INDENT>tile = raw_conf_process_pyramid(raw_conf(mapchete_file)).tile(*tile)<EOL>with mapchete.open(<EOL>mapchete_file,<EOL>mode=mode,<EOL>bounds=tile.bounds,<EOL>zoom=tile.zoom,<EOL>single_input_file=input_file<EOL>) as mp:<EOL><INDENT>spinner.stop()<EOL>tqdm.tqdm.write("<STR_LIT>", file=verbose_dst)<EOL>for result in mp.batch_processor(tile=tile):<EOL><INDENT>utils.write_verbose_msg(result, dst=verbose_dst)<EOL><DEDENT>tqdm.tqdm.write(<EOL>"<STR_LIT>" % mapchete_file, file=verbose_dst<EOL>)<EOL>if vrt:<EOL><INDENT>tqdm.tqdm.write("<STR_LIT>", file=verbose_dst)<EOL>for tile in tqdm.tqdm(<EOL>zoom_index_gen(<EOL>mp=mp,<EOL>zoom=tile.zoom,<EOL>out_dir=(<EOL>idx_out_dir if idx_out_dir else mp.config.output.path<EOL>),<EOL>vrt=vrt,<EOL>),<EOL>total=mp.count_tiles(tile.zoom, tile.zoom),<EOL>unit="<STR_LIT>",<EOL>disable=debug or no_pbar<EOL>):<EOL><INDENT>logger.debug("<STR_LIT>", tile)<EOL><DEDENT>tqdm.tqdm.write(<EOL>"<STR_LIT>" % mapchete_file,<EOL>file=verbose_dst<EOL>)<EOL><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>with mapchete.open(<EOL>mapchete_file,<EOL>mode=mode,<EOL>zoom=zoom,<EOL>bounds=bounds_from_opts(<EOL>wkt_geometry=wkt_geometry,<EOL>point=point,<EOL>bounds=bounds,<EOL>raw_conf=raw_conf(mapchete_file)<EOL>),<EOL>single_input_file=input_file<EOL>) as mp:<EOL><INDENT>spinner.stop()<EOL>tiles_count = mp.count_tiles(<EOL>min(mp.config.init_zoom_levels),<EOL>max(mp.config.init_zoom_levels)<EOL>)<EOL>tqdm.tqdm.write(<EOL>"<STR_LIT>" % (tiles_count, multi),<EOL>file=verbose_dst<EOL>)<EOL>for process_info in tqdm.tqdm(<EOL>mp.batch_processor(<EOL>multi=multi, zoom=zoom, max_chunksize=max_chunksize<EOL>),<EOL>total=tiles_count,<EOL>unit="<STR_LIT>",<EOL>disable=debug or no_pbar<EOL>):<EOL><INDENT>utils.write_verbose_msg(process_info, dst=verbose_dst)<EOL><DEDENT>tqdm.tqdm.write(<EOL>"<STR_LIT>" % mapchete_file, file=verbose_dst<EOL>)<EOL>if vrt:<EOL><INDENT>tqdm.tqdm.write("<STR_LIT>", file=verbose_dst)<EOL>for tile in tqdm.tqdm(<EOL>zoom_index_gen(<EOL>mp=mp,<EOL>zoom=mp.config.init_zoom_levels,<EOL>out_dir=(<EOL>idx_out_dir if idx_out_dir<EOL>else mp.config.output.path<EOL>),<EOL>vrt=vrt<EOL>),<EOL>total=mp.count_tiles(<EOL>min(mp.config.init_zoom_levels),<EOL>max(mp.config.init_zoom_levels)<EOL>),<EOL>unit="<STR_LIT>",<EOL>disable=debug or no_pbar<EOL>):<EOL><INDENT>logger.debug("<STR_LIT>", tile)<EOL><DEDENT>tqdm.tqdm.write(<EOL>"<STR_LIT>" % mapchete_file,<EOL>file=verbose_dst<EOL>)<EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>


app = create_app(<EOL>mapchete_files=[mapchete_file], zoom=zoom,<EOL>bounds=bounds, single_input_file=input_file,<EOL>mode=_get_mode(memory, readonly, overwrite), debug=debug<EOL>)<EOL>if os.environ.get("<STR_LIT>") == "<STR_LIT>":<EOL><INDENT>logger.debug("<STR_LIT>")<EOL><DEDENT>else:<EOL><INDENT>app.run(<EOL>threaded=True, debug=True, port=port, host='<STR_LIT>',<EOL>extra_files=[mapchete_file]<EOL>)<EOL><DEDENT>

Serve a Mapchete process.

Creates the Mapchete host and serves both web page with OpenLayers and the
WMTS simple REST endpoint.


def create_app(<EOL>mapchete_files=None, zoom=None, bounds=None, single_input_file=None,<EOL>mode="<STR_LIT>", debug=None<EOL>):

from flask import Flask, render_template_string<EOL>app = Flask(__name__)<EOL>mapchete_processes = {<EOL>os.path.splitext(os.path.basename(mapchete_file))[<NUM_LIT:0>]: mapchete.open(<EOL>mapchete_file, zoom=zoom, bounds=bounds,<EOL>single_input_file=single_input_file, mode=mode, with_cache=True,<EOL>debug=debug)<EOL>for mapchete_file in mapchete_files<EOL>}<EOL>mp = next(iter(mapchete_processes.values()))<EOL>pyramid_type = mp.config.process_pyramid.grid<EOL>pyramid_srid = mp.config.process_pyramid.crs.to_epsg()<EOL>process_bounds = "<STR_LIT:U+002C>".join([str(i) for i in mp.config.bounds_at_zoom()])<EOL>grid = "<STR_LIT:g>" if pyramid_srid == <NUM_LIT> else "<STR_LIT>"<EOL>web_pyramid = BufferedTilePyramid(pyramid_type)<EOL>@app.route('<STR_LIT:/>', methods=['<STR_LIT:GET>'])<EOL>def index():<EOL><INDENT>"""<STR_LIT>"""<EOL>return render_template_string(<EOL>pkgutil.get_data(<EOL>'<STR_LIT>', '<STR_LIT>').decode("<STR_LIT:utf-8>"),<EOL>srid=pyramid_srid,<EOL>process_bounds=process_bounds,<EOL>is_mercator=(pyramid_srid == <NUM_LIT>),<EOL>process_names=mapchete_processes.keys()<EOL>)<EOL><DEDENT>@app.route(<EOL>"<STR_LIT:/>".join([<EOL>"<STR_LIT>", "<STR_LIT>", "<STR_LIT>", "<STR_LIT>", "<STR_LIT:default>",<EOL>grid, "<STR_LIT>", "<STR_LIT>", "<STR_LIT>"]),<EOL>methods=['<STR_LIT:GET>'])<EOL>def get(mp_name, zoom, row, col, file_ext):<EOL><INDENT>"""<STR_LIT>"""<EOL>logger.debug(<EOL>"<STR_LIT>", zoom, row, col,<EOL>mp_name)<EOL>return _tile_response(<EOL>mapchete_processes[mp_name], web_pyramid.tile(zoom, row, col),<EOL>debug)<EOL><DEDENT>return app<EOL>


if input_formats == output_formats:<EOL><INDENT>show_inputs, show_outputs = True, True<EOL><DEDENT>else:<EOL><INDENT>show_inputs, show_outputs = input_formats, output_formats<EOL><DEDENT>if show_inputs:<EOL><INDENT>click.echo("<STR_LIT>")<EOL>for driver in available_input_formats():<EOL><INDENT>click.echo("<STR_LIT>" % driver)<EOL><DEDENT><DEDENT>if show_outputs:<EOL><INDENT>click.echo("<STR_LIT>")<EOL>for driver in available_output_formats():<EOL><INDENT>click.echo("<STR_LIT>" % driver)<EOL><DEDENT><DEDENT>


bounds = bounds if bounds else None<EOL>options = dict(<EOL>pyramid_type=pyramid_type,<EOL>scale_method=scale_method,<EOL>output_format=output_format,<EOL>resampling=resampling_method,<EOL>zoom=zoom,<EOL>bounds=bounds,<EOL>overwrite=overwrite<EOL>)<EOL>raster2pyramid(input_raster, output_dir, options)<EOL>

Create tile pyramid out of input raster.


def raster2pyramid(input_file, output_dir, options):

pyramid_type = options["<STR_LIT>"]<EOL>scale_method = options["<STR_LIT>"]<EOL>output_format = options["<STR_LIT>"]<EOL>resampling = options["<STR_LIT>"]<EOL>zoom = options["<STR_LIT>"]<EOL>bounds = options["<STR_LIT>"]<EOL>mode = "<STR_LIT>" if options["<STR_LIT>"] else "<STR_LIT>"<EOL>minzoom, maxzoom = _get_zoom(zoom, input_file, pyramid_type)<EOL>with rasterio.open(input_file, "<STR_LIT:r>") as input_raster:<EOL><INDENT>output_bands = input_raster.count<EOL>input_dtype = input_raster.dtypes[<NUM_LIT:0>]<EOL>output_dtype = input_raster.dtypes[<NUM_LIT:0>]<EOL>nodataval = input_raster.nodatavals[<NUM_LIT:0>]<EOL>nodataval = nodataval if nodataval else <NUM_LIT:0><EOL>if output_format == "<STR_LIT>" and output_bands > <NUM_LIT:3>:<EOL><INDENT>output_bands = <NUM_LIT:3><EOL>output_dtype = '<STR_LIT>'<EOL><DEDENT>scales_minmax = ()<EOL>if scale_method == "<STR_LIT>":<EOL><INDENT>for index in range(<NUM_LIT:1>, output_bands+<NUM_LIT:1>):<EOL><INDENT>scales_minmax += (DTYPE_RANGES[input_dtype], )<EOL><DEDENT><DEDENT>elif scale_method == "<STR_LIT>":<EOL><INDENT>for index in range(<NUM_LIT:1>, output_bands+<NUM_LIT:1>):<EOL><INDENT>band = input_raster.read(index)<EOL>scales_minmax += ((band.min(), band.max()), )<EOL><DEDENT><DEDENT>elif scale_method == "<STR_LIT>":<EOL><INDENT>for index in range(<NUM_LIT:1>, output_bands+<NUM_LIT:1>):<EOL><INDENT>scales_minmax += ((<NUM_LIT:0>, <NUM_LIT:255>), )<EOL><DEDENT><DEDENT>if input_dtype == "<STR_LIT>":<EOL><INDENT>scale_method = None<EOL>scales_minmax = ()<EOL>for index in range(<NUM_LIT:1>, output_bands+<NUM_LIT:1>):<EOL><INDENT>scales_minmax += ((None, None), )<EOL><DEDENT><DEDENT><DEDENT>config = dict(<EOL>process="<STR_LIT>",<EOL>output={<EOL>"<STR_LIT:path>": output_dir,<EOL>"<STR_LIT>": output_format,<EOL>"<STR_LIT>": output_bands,<EOL>"<STR_LIT>": output_dtype<EOL>},<EOL>pyramid=dict(pixelbuffer=<NUM_LIT:5>, grid=pyramid_type),<EOL>scale_method=scale_method,<EOL>scales_minmax=scales_minmax,<EOL>input={"<STR_LIT>": input_file},<EOL>config_dir=os.getcwd(),<EOL>zoom_levels=dict(min=minzoom, max=maxzoom),<EOL>nodataval=nodataval,<EOL>resampling=resampling,<EOL>bounds=bounds,<EOL>baselevel={"<STR_LIT>": maxzoom, "<STR_LIT>": resampling},<EOL>mode=mode<EOL>)<EOL>with mapchete.open(config, zoom=zoom, bounds=bounds) as mp:<EOL><INDENT>if not os.path.exists(output_dir):<EOL><INDENT>os.makedirs(output_dir)<EOL><DEDENT>mp.batch_process(zoom=[minzoom, maxzoom])<EOL><DEDENT>

Create a tile pyramid out of an input raster dataset.


def _get_zoom(zoom, input_raster, pyramid_type):

if not zoom:<EOL><INDENT>minzoom = <NUM_LIT:1><EOL>maxzoom = get_best_zoom_level(input_raster, pyramid_type)<EOL><DEDENT>elif len(zoom) == <NUM_LIT:1>:<EOL><INDENT>minzoom = zoom[<NUM_LIT:0>]<EOL>maxzoom = zoom[<NUM_LIT:0>]<EOL><DEDENT>elif len(zoom) == <NUM_LIT:2>:<EOL><INDENT>if zoom[<NUM_LIT:0>] < zoom[<NUM_LIT:1>]:<EOL><INDENT>minzoom = zoom[<NUM_LIT:0>]<EOL>maxzoom = zoom[<NUM_LIT:1>]<EOL><DEDENT>else:<EOL><INDENT>minzoom = zoom[<NUM_LIT:1>]<EOL>maxzoom = zoom[<NUM_LIT:0>]<EOL><DEDENT><DEDENT>return minzoom, maxzoom<EOL>

Determine minimum and maximum zoomlevel.


try:<EOL><INDENT>prev_timezone = os.environ['<STR_LIT>']<EOL><DEDENT>except KeyError:<EOL><INDENT>prev_timezone = None<EOL><DEDENT>os.environ['<STR_LIT>'] = TZ<EOL>time.tzset()  <EOL>return prev_timezone<EOL>


def wgs84_distance(lat1, lon1, lat2, lon2):

dLat = math.radians(lat2 - lat1)<EOL>dLon = math.radians(lon2 - lon1)<EOL>a = (math.sin(dLat / <NUM_LIT:2>) * math.sin(dLat / <NUM_LIT:2>) +<EOL>math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) *<EOL>math.sin(dLon / <NUM_LIT:2>) * math.sin(dLon / <NUM_LIT:2>))<EOL>c = <NUM_LIT:2> * math.atan2(math.sqrt(a), math.sqrt(<NUM_LIT:1> - a))<EOL>d = EARTH_RADIUS * c<EOL>return d<EOL>

Distance (in meters) between two points in WGS84 coord system.


@contextlib.contextmanager<EOL>def create_file(fname=None, fname_tmp=None, tmpdir=None,<EOL>save_tmpfile=False, keepext=False):

<EOL>if fname == '<STR_LIT>':<EOL><INDENT>yield fname<EOL>return<EOL><DEDENT>if fname_tmp is None:<EOL><INDENT>basename = os.path.basename(fname)<EOL>root, ext = os.path.splitext(basename)<EOL>dir_ = this_dir = os.path.dirname(fname)<EOL>if not keepext:<EOL><INDENT>root = root + ext<EOL>ext = '<STR_LIT>'<EOL><DEDENT>if tmpdir:<EOL><INDENT>if tmpdir is True:<EOL><INDENT>for dir__ in possible_tmpdirs:<EOL><INDENT>if os.access(dir__, os.F_OK):<EOL><INDENT>dir_ = dir__<EOL>break<EOL><DEDENT><DEDENT><DEDENT><DEDENT>tmpfile = tempfile.NamedTemporaryFile(<EOL>prefix='<STR_LIT>' + root + '<STR_LIT:->', suffix=ext, dir=dir_, delete=False)<EOL>fname_tmp = tmpfile.name<EOL><DEDENT>try:<EOL><INDENT>yield fname_tmp<EOL><DEDENT>except Exception as e:<EOL><INDENT>if save_tmpfile:<EOL><INDENT>print("<STR_LIT>" % fname_tmp)<EOL><DEDENT>else:<EOL><INDENT>os.unlink(fname_tmp)<EOL><DEDENT>raise<EOL><DEDENT>try:<EOL><INDENT>os.rename(fname_tmp, fname)<EOL>os.chmod(fname, <NUM_LIT> & ~current_umask)<EOL><DEDENT>except OSError as e:<EOL><INDENT>tmpfile2 = tempfile.NamedTemporaryFile(<EOL>prefix='<STR_LIT>' + root + '<STR_LIT:->', suffix=ext, dir=this_dir, delete=False)<EOL>shutil.copy(fname_tmp, tmpfile2.name)<EOL>os.rename(tmpfile2.name, fname)<EOL>os.chmod(fname, <NUM_LIT> & ~current_umask)<EOL>os.unlink(fname_tmp)<EOL><DEDENT>

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.


stmt = args[<NUM_LIT:0>]<EOL>if len(args) > <NUM_LIT:1>:<EOL><INDENT>stmt = stmt.replace('<STR_LIT:%>', '<STR_LIT>').replace('<STR_LIT:?>', '<STR_LIT>')<EOL>print(stmt % (args[<NUM_LIT:1>]))<EOL><DEDENT>return cur.execute(*args)<EOL>

Utility function to print sqlite queries before executing.

    Use instead of cur.execute().  First argument is cursor.

    cur.execute(stmt)
    becomes
    util.execute(cur, stmt)


t = str(time).split('<STR_LIT::>')<EOL>seconds = int(t[<NUM_LIT:0>]) * <NUM_LIT> + int(t[<NUM_LIT:1>]) * <NUM_LIT> + int(t[<NUM_LIT:2>])<EOL>return seconds<EOL>

Converts time strings to integer seconds
:param time: %H:%M:%S string
:return: integer seconds


if not os.path.isdir(path):<EOL><INDENT>os.makedirs(path)<EOL><DEDENT>return path<EOL>

Create directories if they do not exist, otherwise do nothing.

Return path for convenience


def timed(*args, **kw):<EOL><INDENT>time_start = time.time()<EOL>result = method(*args, **kw)<EOL>time_end = time.time()<EOL>print('<STR_LIT>' % (method.__name__, time_end - time_start))<EOL>return result<EOL><DEDENT>return timed<EOL>

A Python decorator for printing out the execution time for a function.

Adapted from:
www.andreas-jung.com/contents/a-python-decorator-for-measuring-the-execution-time-of-methods


def source_csv_to_pandas(path, table, read_csv_args=None):

if '<STR_LIT>' not in table:<EOL><INDENT>table += '<STR_LIT>'<EOL><DEDENT>if isinstance(path, dict):<EOL><INDENT>data_obj = path[table]<EOL>f = data_obj.split("<STR_LIT:\n>")<EOL><DEDENT>else:<EOL><INDENT>if os.path.isdir(path):<EOL><INDENT>f = open(os.path.join(path, table))<EOL><DEDENT>else:<EOL><INDENT>z = zipfile.ZipFile(path)<EOL>for path in z.namelist():<EOL><INDENT>if table in path:<EOL><INDENT>table = path<EOL>break<EOL><DEDENT><DEDENT>try:<EOL><INDENT>f = zip_open(z, table)<EOL><DEDENT>except KeyError as e:<EOL><INDENT>return pd.DataFrame()<EOL><DEDENT><DEDENT><DEDENT>if read_csv_args:<EOL><INDENT>df = pd.read_csv(**read_csv_args)<EOL><DEDENT>else:<EOL><INDENT>df = pd.read_csv(f)<EOL><DEDENT>return df<EOL>

Parameters
----------
path: str
    path to directory or zipfile
table: str
    name of table
read_csv_args:
    string arguments passed to the read_csv function

Returns
-------
df: pandas:DataFrame


import matplotlib.pyplot as plt<EOL>fig = plt.figure()<EOL>node_coords = {}<EOL>for node, data in net.nodes(data=True):<EOL><INDENT>node_coords[node] = (data['<STR_LIT>'], data['<STR_LIT>'])<EOL><DEDENT>ax = fig.add_subplot(<NUM_LIT>)<EOL>networkx.draw(net, pos=node_coords, ax=ax, node_size=<NUM_LIT:50>)<EOL>return fig<EOL>

Plot a networkx.Graph by using the lat and lon attributes of nodes.
Parameters
----------
net : networkx.Graph
Returns
-------
fig : matplotlib.figure
    the figure object where the network is plotted


def difference_of_pandas_dfs(df_self, df_other, col_names=None):

df = pd.concat([df_self, df_other])<EOL>df = df.reset_index(drop=True)<EOL>df_gpby = df.groupby(col_names)<EOL>idx = [x[<NUM_LIT:0>] for x in list(df_gpby.groups.values()) if len(x) == <NUM_LIT:1>]<EOL>df_sym_diff = df.reindex(idx)<EOL>df_diff = pd.concat([df_other, df_sym_diff])<EOL>df_diff = df_diff.reset_index(drop=True)<EOL>df_gpby = df_diff.groupby(col_names)<EOL>idx = [x[<NUM_LIT:0>] for x in list(df_gpby.groups.values()) if len(x) == <NUM_LIT:2>]<EOL>df_diff = df_diff.reindex(idx)<EOL>return df_diff<EOL>

Returns a dataframe with all of df_other that are not in df_self, when considering the columns specified in col_names
:param df_self: pandas Dataframe
:param df_other: pandas Dataframe
:param col_names: list of column names
:return:


cur = self._gtfs.get_cursor()<EOL>cur.execute('''<STR_LIT>''')<EOL>

Get segment

Returns
-------
segments: list[Segment]


from gtfspy import shapes<EOL>cur = conn.cursor()<EOL>breakpoints_cache = {}<EOL>count_bad_shape_ordering = <NUM_LIT:0><EOL>count_bad_shape_fit = <NUM_LIT:0><EOL>count_no_shape_fit = <NUM_LIT:0><EOL>trip_Is = [x[<NUM_LIT:0>] for x in<EOL>cur.execute('<STR_LIT>').fetchall()]<EOL>for trip_I in trip_Is:<EOL><INDENT>row = cur.execute('''<STR_LIT>''', (trip_I,)).fetchone()<EOL>if row is None:<EOL><INDENT>continue<EOL><DEDENT>shape_id = row[<NUM_LIT:0>]<EOL>if shape_id is None or shape_id == '<STR_LIT>':<EOL><INDENT>continue<EOL><DEDENT>cur.execute('''<STR_LIT>''',<EOL>(trip_I,))<EOL>stop_points = [dict(seq=row[<NUM_LIT:0>],<EOL>lat=row[<NUM_LIT:1>],<EOL>lon=row[<NUM_LIT:2>],<EOL>stop_I=row[<NUM_LIT:3>])<EOL>for row in cur if row[<NUM_LIT:1>] and row[<NUM_LIT:2>]]<EOL>cache_key = (shape_id, tuple(x['<STR_LIT>'] for x in stop_points))<EOL>if cache_key in breakpoints_cache:<EOL><INDENT>breakpoints = breakpoints_cache[cache_key]<EOL><DEDENT>else:<EOL><INDENT>shape_points = shapes.get_shape_points(cur, shape_id)<EOL>breakpoints, badness= shapes.find_segments(stop_points, shape_points)<EOL>if breakpoints != sorted(breakpoints):<EOL><INDENT>count_bad_shape_ordering += <NUM_LIT:1><EOL>breakpoints_cache[cache_key] = None<EOL>continue  <EOL><DEDENT>breakpoints_cache[cache_key] = breakpoints<EOL>if badness > <NUM_LIT:30> * len(breakpoints):<EOL><INDENT>count_bad_shape_fit += <NUM_LIT:1><EOL><DEDENT><DEDENT>if breakpoints is None:<EOL><INDENT>continue<EOL><DEDENT>if len(breakpoints) == <NUM_LIT:0>:<EOL><INDENT>count_no_shape_fit += <NUM_LIT:1><EOL>continue<EOL><DEDENT>assert len(breakpoints) == len(stop_points)<EOL>cur.executemany('<STR_LIT>'<EOL>'<STR_LIT>',<EOL>((int(bkpt), int(trip_I), int(stpt['<STR_LIT>']))<EOL>for bkpt, stpt in zip(breakpoints, stop_points)))<EOL><DEDENT>if count_bad_shape_fit > <NUM_LIT:0>:<EOL><INDENT>print("<STR_LIT>" % count_bad_shape_fit)<EOL><DEDENT>if count_bad_shape_ordering > <NUM_LIT:0>:<EOL><INDENT>print("<STR_LIT>" % count_bad_shape_ordering)<EOL><DEDENT>if count_no_shape_fit > <NUM_LIT:0>:<EOL><INDENT>print("<STR_LIT>" % count_no_shape_fit)<EOL><DEDENT>conn.commit()<EOL>

Pre-compute the shape points corresponding to each trip's stop.

    Depends: shapes


def __init__(self, gtfssource=None, print_progress=True):

if isinstance(gtfssource, string_types + (dict,)):<EOL><INDENT>_gtfs_sources = [gtfssource]<EOL><DEDENT>else:<EOL><INDENT>assert isinstance(gtfssource, list)<EOL>_gtfs_sources = gtfssource<EOL><DEDENT>self.print_progress = print_progress<EOL>self.gtfs_sources = []<EOL>for source in _gtfs_sources:<EOL><INDENT>if isinstance(source, dict):<EOL><INDENT>self.gtfs_sources.append(source)<EOL><DEDENT>elif isinstance(source, string_types):<EOL><INDENT>if os.path.isdir(source):<EOL><INDENT>self.gtfs_sources.append(source)<EOL><DEDENT>else:<EOL><INDENT>z = zipfile.ZipFile(source, mode='<STR_LIT:r>')<EOL>zip_commonprefix = os.path.commonprefix(z.namelist())<EOL>zip_source_datum = {<EOL>"<STR_LIT>": source,<EOL>"<STR_LIT>": zip_commonprefix<EOL>}<EOL>self.gtfs_sources.append(zip_source_datum)<EOL><DEDENT><DEDENT><DEDENT>

Parameters
----------
gtfssource: str, dict, list
    str: path to GTFS directory or zipfile
    dict:
        dictionary of files to use to as the GTFS files.  This
        is mainly useful for testing, not for any normal use of
        GTFS.  For example, to provide an agency.txt file,
        do this:
            d = {'agency.txt':
                     'agency_id, agency_name, agency_timezone,agency_url\n' \
                     '555,CompNet,Europe/Lala,http://x'
                  }
        Of course you probably wouldn't want all the string data
        inline like that. You can provide the data as a string or
        a file-like object (with a .read() attribute and line
        iteration).
    list: a list of the above elements to import (i.e. "merge") multiple GTFS feeds to the same database

print_progress: boolean
    whether to print progress of the


<EOL>return any(self.exists_by_source())<EOL>

Does this GTFS contain this file? (file specified by the class)


exists_list = []<EOL>for source in self.gtfs_sources:<EOL><INDENT>if isinstance(source, dict):<EOL><INDENT>if self.fname in source:<EOL><INDENT>if source[self.fname]:<EOL><INDENT>exists_list.append(True)<EOL>continue<EOL><DEDENT><DEDENT><DEDENT>if "<STR_LIT>" in source:<EOL><INDENT>try:<EOL><INDENT>Z = zipfile.ZipFile(source['<STR_LIT>'], mode='<STR_LIT:r>')<EOL>Z.getinfo(os.path.join(source['<STR_LIT>'], self.fname))<EOL>exists_list.append(True)<EOL>continue<EOL><DEDENT>except KeyError:<EOL><INDENT>print(self.fname, '<STR_LIT>', source)<EOL>exists_list.append(False)<EOL>continue<EOL><DEDENT><DEDENT>elif isinstance(source, string_types):<EOL><INDENT>if os.path.exists(os.path.join(source, self.fname)):<EOL><INDENT>exists_list.append(True)<EOL>continue<EOL><DEDENT><DEDENT>exists_list.append(False)<EOL><DEDENT>return exists_list<EOL>


return self.gen_rows(*(self._get_csv_reader_generators()))<EOL>

Iterate through all rows in all files file.

        The file is specified by the class - there is one class per
        table.  This opens the file, does basic sanitaition, and
        iterates over all rows as dictionaries, converted by
        csv.DictReader.  This function opens files from both .zip and
        raw directories.  The actual logic of converting all data to
        Python is done in the .gen_rows() method which must be
        defined in each subclass.


<EOL>cur = conn.cursor()<EOL>if self.tabledef is None:<EOL><INDENT>return<EOL><DEDENT>if not self.tabledef.startswith('<STR_LIT>'):<EOL><INDENT>cur.execute('<STR_LIT>'<EOL>% (self.table, self.tabledef)<EOL>)<EOL><DEDENT>else:<EOL><INDENT>cur.execute(self.tabledef)<EOL><DEDENT>conn.commit()<EOL>


cur = conn.cursor()<EOL>csv_reader_generators, prefixes = self._get_csv_reader_generators()<EOL>for csv_reader, prefix in zip(csv_reader_generators, prefixes):<EOL><INDENT>try:<EOL><INDENT>row = next(iter(self.gen_rows([csv_reader], [prefix])))<EOL>fields = row.keys()<EOL><DEDENT>except StopIteration:<EOL><INDENT>print("<STR_LIT>" % (self.fname, self.table, prefix))<EOL>continue<EOL><DEDENT>stmt = '''<STR_LIT>''' % (<EOL>self.table,<EOL>('<STR_LIT:U+002CU+0020>'.join([x for x in fields if x[<NUM_LIT:0>] != '<STR_LIT:_>'] + self.extra_keys)),<EOL>('<STR_LIT:U+002CU+0020>'.join(["<STR_LIT::>" + x for x in fields if x[<NUM_LIT:0>] != '<STR_LIT:_>'] + self.extra_values))<EOL>)<EOL>if self.print_progress:<EOL><INDENT>print('<STR_LIT>' % (self.fname, self.table, prefix))<EOL><DEDENT>from itertools import chain<EOL>rows = chain([row], self.gen_rows([csv_reader], [prefix]))<EOL>cur.executemany(stmt, rows)<EOL>conn.commit()<EOL><DEDENT>


if self.print_progress:<EOL><INDENT>print('<STR_LIT>', self.__class__.__name__)<EOL><DEDENT>self._conn = conn<EOL>self.create_table(conn)<EOL>if self.mode in ('<STR_LIT:all>', '<STR_LIT>') and self.fname and self.exists() and self.table not in ignore_tables:<EOL><INDENT>self.insert_data(conn)<EOL><DEDENT>if self.mode in ('<STR_LIT:all>', '<STR_LIT:index>') and hasattr(self, '<STR_LIT:index>'):<EOL><INDENT>self.create_index(conn)<EOL><DEDENT>if self.mode in ('<STR_LIT:all>', '<STR_LIT>') and hasattr(self, '<STR_LIT>'):<EOL><INDENT>self.run_post_import(conn)<EOL><DEDENT>conn.commit()<EOL>

Do the actual import. Copy data and store in connection object.

        This function:
        - Creates the tables
        - Imports data (using self.gen_rows)
        - Run any post_import hooks.
        - Creates any indexs
        - Does *not* run self.make_views - those must be done
          after all tables are loaded.


pass<EOL>

The make views should be run after all tables imported.


@classmethod<EOL><INDENT>def copy(cls, conn, **where):<DEDENT>

cur = conn.cursor()<EOL>if where and cls.copy_where:<EOL><INDENT>copy_where = cls.copy_where.format(**where)<EOL><DEDENT>else:<EOL><INDENT>copy_where = '<STR_LIT>'<EOL><DEDENT>cur.execute('<STR_LIT>'<EOL>'<STR_LIT>' % (cls.table, cls.table, copy_where))<EOL>

Copy data from one table to another while filtering data at the same time

        Parameters
        ----------
        conn: sqlite3 DB connection.  It must have a second database
            attached as "other".
        **where : keyword arguments
            specifying (start_ut and end_ut for filtering, see the copy_where clause in the subclasses)


Create day_trips and day_stop_times views.

        day_trips:  day_trips2 x trips  = days x trips
        day_stop_times: day_trips2 x trips x stop_times = days x trips x stop_times


cax, kw = matplotlib.colorbar.make_axes(matplotlib.pyplot.gca())<EOL>c = matplotlib.colorbar.ColorbarBase(cax, cmap=cmap, norm=norm)<EOL>return c<EOL>

Create a colourbar with limits of lwr and upr


lat = [row['<STR_LIT>'] for row in rows]<EOL>lon = [row['<STR_LIT>'] for row in rows]<EOL>print('<STR_LIT>'+'<STR_LIT:->' * <NUM_LIT:5>)<EOL>print("<STR_LIT>" % (prefix, prefix, lat, lon))<EOL>print('<STR_LIT:->'*<NUM_LIT:5>)<EOL>

Print coordinates within a sequence.

    This is only used for debugging.  Printed in a form that can be
    pasted into Python for visualization.


if not shape:<EOL><INDENT>return [], <NUM_LIT:0><EOL><DEDENT>break_points = []<EOL>last_i = <NUM_LIT:0><EOL>cumul_d = <NUM_LIT:0><EOL>badness = <NUM_LIT:0><EOL>d_last_stop = float('<STR_LIT>')<EOL>lstlat, lstlon = None, None<EOL>break_shape_points = []<EOL>for stop in stops:<EOL><INDENT>stlat, stlon = stop['<STR_LIT>'], stop['<STR_LIT>']<EOL>best_d = float('<STR_LIT>')<EOL>if badness > <NUM_LIT> and badness > <NUM_LIT:30> * len(break_points):<EOL><INDENT>return [], badness<EOL><DEDENT>for i in range(last_i, len(shape)):<EOL><INDENT>d = wgs84_distance(stlat, stlon, shape[i]['<STR_LIT>'], shape[i]['<STR_LIT>'])<EOL>if lstlat:<EOL><INDENT>d_last_stop = wgs84_distance(lstlat, lstlon, shape[i]['<STR_LIT>'], shape[i]['<STR_LIT>'])<EOL><DEDENT>if d < best_d:<EOL><INDENT>best_d = d<EOL>best_i = i<EOL>cumul_d += d<EOL><DEDENT>if (d_last_stop < d) or (d > <NUM_LIT>) or (i < best_i + <NUM_LIT:100>):<EOL><INDENT>continue<EOL><DEDENT>else:<EOL><INDENT>badness += best_d<EOL>break_points.append(best_i)<EOL>last_i = best_i<EOL>lstlat, lstlon = stlat, stlon<EOL>break_shape_points.append(shape[best_i])<EOL>break<EOL><DEDENT><DEDENT>else:<EOL><INDENT>badness += best_d<EOL>break_points.append(best_i)<EOL>last_i = best_i<EOL>lstlat, lstlon = stlat, stlon<EOL>break_shape_points.append(shape[best_i])<EOL>pass<EOL><DEDENT><DEDENT>return break_points, badness<EOL>

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.


def find_best_segments(cur, stops, shape_ids, route_id=None,<EOL>breakpoints_cache=None):

cache_key = None<EOL>if breakpoints_cache is not None:<EOL><INDENT>cache_key = (route_id, tuple(x['<STR_LIT>'] for x in stops))<EOL>if cache_key in breakpoints_cache:<EOL><INDENT>print('<STR_LIT>')<EOL>return breakpoints_cache[cache_key]<EOL><DEDENT><DEDENT>if route_id is not None:<EOL><INDENT>cur.execute('''<STR_LIT>''',<EOL>(route_id,))<EOL>data = cur.fetchall()<EOL>if not data:<EOL><INDENT>print("<STR_LIT>" % route_id)<EOL>return [], None, None, None<EOL><DEDENT>shape_ids = zip(*data)[<NUM_LIT:0>]<EOL><DEDENT>results = []<EOL>for shape_id in shape_ids:<EOL><INDENT>shape = get_shape_points(cur, shape_id)<EOL>breakpoints, badness = find_segments(stops, shape)<EOL>results.append([badness, breakpoints, shape, shape_id])<EOL>if len(stops) > <NUM_LIT:5> and badness < <NUM_LIT:5>*(len(stops)):<EOL><INDENT>break<EOL><DEDENT><DEDENT>best = np.argmin(zip(*results)[<NUM_LIT:0>])<EOL>badness = results[best][<NUM_LIT:0>]<EOL>breakpoints = results[best][<NUM_LIT:1>]<EOL>shape = results[best][<NUM_LIT:2>]<EOL>shape_id = results[best][<NUM_LIT:3>]<EOL>if breakpoints_cache is not None:<EOL><INDENT>print("<STR_LIT>", cache_key[<NUM_LIT:0>], hash(cache_key[<NUM_LIT:1>:]))<EOL>breakpoints_cache[cache_key] = breakpoints, badness, shape, shape_id<EOL><DEDENT>return breakpoints, badness, shape, shape_id<EOL>

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.


<EOL>segs = []<EOL>bp = <NUM_LIT:0> <EOL>bp2 = <NUM_LIT:0><EOL>for i in range(len(break_points)-<NUM_LIT:1>):<EOL><INDENT>bp = break_points[i] if break_points[i] is not None else bp2<EOL>bp2 = break_points[i+<NUM_LIT:1>] if break_points[i+<NUM_LIT:1>] is not None else bp<EOL>segs.append(shape[bp:bp2+<NUM_LIT:1>])<EOL><DEDENT>segs.append([])<EOL>return segs<EOL>

Break a shape into segments between stops using break_points.

    This function can use the `break_points` outputs from
    `find_segments`, and cuts the shape-sequence into pieces
    corresponding to each stop.


stops[<NUM_LIT:0>]['<STR_LIT:d>'] = <NUM_LIT:0.0><EOL>for i in range(<NUM_LIT:1>, len(stops)):<EOL><INDENT>stops[i]['<STR_LIT:d>'] = stops[i-<NUM_LIT:1>]['<STR_LIT:d>'] + wgs84_distance(<EOL>stops[i-<NUM_LIT:1>]['<STR_LIT>'], stops[i-<NUM_LIT:1>]['<STR_LIT>'],<EOL>stops[i]['<STR_LIT>'], stops[i]['<STR_LIT>'],<EOL>)<EOL><DEDENT>for stop in stops:<EOL><INDENT>stop['<STR_LIT:d>'] = int(stop['<STR_LIT:d>'])<EOL><DEDENT>

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


cur.execute('''<STR_LIT>''', (shape_id,))<EOL>shape_points = [dict(seq=row[<NUM_LIT:0>], lat=row[<NUM_LIT:1>], lon=row[<NUM_LIT:2>], d=row[<NUM_LIT:3>])<EOL>for row in cur]<EOL>return shape_points<EOL>

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('''<STR_LIT>''', (shape_id,))<EOL>shape_points = {'<STR_LIT>': [], '<STR_LIT>':  [], '<STR_LIT>': [], '<STR_LIT:d>': []}<EOL>for row in cur:<EOL><INDENT>shape_points['<STR_LIT>'].append(row[<NUM_LIT:0>])<EOL>shape_points['<STR_LIT>'].append(row[<NUM_LIT:1>])<EOL>shape_points['<STR_LIT>'].append(row[<NUM_LIT:2>])<EOL>shape_points['<STR_LIT:d>'].append(row[<NUM_LIT:3>])<EOL><DEDENT>return shape_points<EOL>

Given a shape_id, return its shape-sequence (as a dict of lists).
get_shape_points function returns them as a list of dicts

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

Returns
-------
shape_points: dict of lists
    dict contains keys 'seq', 'lat', 'lon', and 'd'(istance) of the shape


cur.execute('''<STR_LIT>''', (route_id,))<EOL>shape_points = [dict(seq=row[<NUM_LIT:0>], lat=row[<NUM_LIT:1>], lon=row[<NUM_LIT:2>]) for row in cur]<EOL>return shape_points<EOL>

Given a route_id, return its stop-sequence.

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

Returns
-------
shape_points: list
    elements are dictionaries containing the 'seq', 'lat', and 'lon' of the shape


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<EOL>if not shape_breaks:<EOL><INDENT>shape_breaks = []<EOL>for seq_stop in [seq_stop1, seq_stop2]:<EOL><INDENT>query = """<STR_LIT>""" % (trip_I, seq_stop)<EOL>for row in cur.execute(query):<EOL><INDENT>shape_breaks.append(row[<NUM_LIT:0>])<EOL><DEDENT><DEDENT><DEDENT>assert len(shape_breaks) == <NUM_LIT:2><EOL>query = """<STR_LIT>""" % (trip_I, shape_breaks[<NUM_LIT:0>], shape_breaks[<NUM_LIT:1>])<EOL>shapedict = {'<STR_LIT>': [], '<STR_LIT>': [], '<STR_LIT>': []}<EOL>for row in cur.execute(query):<EOL><INDENT>shapedict['<STR_LIT>'].append(row[<NUM_LIT:0>])<EOL>shapedict['<STR_LIT>'].append(row[<NUM_LIT:1>])<EOL>shapedict['<STR_LIT>'].append(row[<NUM_LIT:2>])<EOL><DEDENT>return shapedict<EOL>

Given a trip_I (shortened id), return shape points between two stops
(seq_stop1 and seq_stop2).

Trip_I is used for matching obtaining the full shape of one trip (route).
From the resulting shape we then obtain only shape points between
stop_seq1 and stop_seq2
trip_I---(trips)--->shape_id
trip_I, seq_stop1----(stop_times)---> shape_break1
trip_I, seq_stop2----(stop_times)---> shape_break2
shapes_id+shape_break1+shape_break2 --(shapes)--> result

Parameters
----------
cur : sqlite3.Cursor
    cursor to sqlite3 DB containing GTFS
trip_I : int
    transformed trip_id (i.e. a new column that is created when
    GTFS is imported to a DB)
seq_stop1: int
    a positive inger describing the index of the point of the shape that
    corresponds to the first stop
seq_stop2: int
    a positive inger describing the index of the point of the shape that
    corresponds to the second stop
shape_breaks: ??

Returns
-------
shapedict: dict
    Dictionary containing the latitudes and longitudes:
        lats=shapedict['lat']
        lons=shapedict['lon']


def get_trip_points(cur, route_id, offset=<NUM_LIT:0>, tripid_glob='<STR_LIT>'):

extra_where = '<STR_LIT>'<EOL>if tripid_glob:<EOL><INDENT>extra_where = "<STR_LIT>" % tripid_glob<EOL><DEDENT>cur.execute('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' % extra_where, (route_id, offset))<EOL>stop_points = [dict(seq=row[<NUM_LIT:0>], lat=row[<NUM_LIT:1>], lon=row[<NUM_LIT:2>]) for row in cur]<EOL>return stop_points<EOL>

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.


def interpolate_shape_times(shape_distances, shape_breaks, stop_times):

shape_times = np.zeros(len(shape_distances))<EOL>shape_times[:shape_breaks[<NUM_LIT:0>]] = stop_times[<NUM_LIT:0>]<EOL>for i in range(len(shape_breaks)-<NUM_LIT:1>):<EOL><INDENT>cur_break = shape_breaks[i]<EOL>cur_time = stop_times[i]<EOL>next_break = shape_breaks[i+<NUM_LIT:1>]<EOL>next_time = stop_times[i+<NUM_LIT:1>]<EOL>if cur_break == next_break:<EOL><INDENT>shape_times[cur_break] = stop_times[i]<EOL><DEDENT>else:<EOL><INDENT>cur_distances = shape_distances[cur_break:next_break+<NUM_LIT:1>]<EOL>norm_distances = ((np.array(cur_distances)-float(cur_distances[<NUM_LIT:0>])) /<EOL>float(cur_distances[-<NUM_LIT:1>] - cur_distances[<NUM_LIT:0>]))<EOL>times = (<NUM_LIT:1.>-norm_distances)*cur_time+norm_distances*next_time<EOL>shape_times[cur_break:next_break] = times[:-<NUM_LIT:1>]<EOL><DEDENT><DEDENT>shape_times[shape_breaks[-<NUM_LIT:1>]:] = stop_times[-<NUM_LIT:1>]<EOL>return list(shape_times)<EOL>

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.


lons, lats = _get_stop_lat_lons(gtfs)<EOL>lon_lats = list(zip(lons, lats))<EOL>polygon = MultiPoint(lon_lats).convex_hull<EOL>hull_lons, hull_lats= polygon.exterior.coords.xy<EOL>return hull_lats, hull_lons<EOL>

Parameters
----------
gtfs: gtfs.GTFS

Returns
-------
lons: list
    of floats
lats: list
    of floats


def get_buffered_area_of_stops(gtfs, buffer_meters, resolution):

lons, lats = _get_stop_lat_lons(gtfs)<EOL>a = compute_buffered_area_of_stops(lats, lons, buffer_meters, resolution)<EOL>return a<EOL>

Compute the total area of all buffered stops in PT network.

Parameters
----------
gtfs: gtfs.GTFS
buffer_meters: meters around the stop to buffer.
resolution: increases the accuracy of the calculated area with computation time. Default = 16

Returns
-------
Total area covered by the buffered stops in square meters.


def __init__(self, gtfs, start_time_ut, lat, lon, max_duration_ut, min_transfer_time=<NUM_LIT:30>,<EOL>shapes=True, walk_speed=<NUM_LIT:0.5>):

self.gtfs = gtfs<EOL>self.start_time_ut = start_time_ut<EOL>self.lat = lat<EOL>self.lon = lon<EOL>self.max_duration_ut = max_duration_ut<EOL>self.min_transfer_time = min_transfer_time<EOL>self.shapes = shapes<EOL>self.event_heap = None<EOL>self.walk_speed = walk_speed<EOL>self._uninfected_stops = None<EOL>self._stop_I_to_spreading_stop = None<EOL>self._initialized = False<EOL>self._has_run = False<EOL>

Parameters
----------
gtfs: GTFS
    the underlying GTFS (database) connection for getting data
start_time_ut: number
    Start time of the spreading.
lat: float
    latitude of the spreading seed location
lon: float
    longitude of the spreading seed location
max_duration_ut: int
    maximum duration of the spreading process (in seconds)
min_transfer_time : int
    minimum transfer time in seconds
shapes : bool
    whether to include shapes


if self._has_run:<EOL><INDENT>raise RuntimeError("<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>i = <NUM_LIT:1><EOL>while self.event_heap.size() > <NUM_LIT:0> and len(self._uninfected_stops) > <NUM_LIT:0>:<EOL><INDENT>event = self.event_heap.pop_next_event()<EOL>this_stop = self._stop_I_to_spreading_stop[event.from_stop_I]<EOL>if event.arr_time_ut > self.start_time_ut + self.max_duration_ut:<EOL><INDENT>break<EOL><DEDENT>if this_stop.can_infect(event):<EOL><INDENT>target_stop = self._stop_I_to_spreading_stop[event.to_stop_I]<EOL>already_visited = target_stop.has_been_visited()<EOL>target_stop.visit(event)<EOL>if not already_visited:<EOL><INDENT>self._uninfected_stops.remove(event.to_stop_I)<EOL>print(i, self.event_heap.size())<EOL>transfer_distances = self.gtfs.get_straight_line_transfer_distances(event.to_stop_I)<EOL>self.event_heap.add_walk_events_to_heap(transfer_distances, event, self.start_time_ut,<EOL>self.walk_speed, self._uninfected_stops,<EOL>self.max_duration_ut)<EOL>i += <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT>self._has_run = True<EOL>


if not self.visit_events:<EOL><INDENT>return float('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>return min(self.visit_events, key=lambda event: event.arr_time_ut).arr_time_ut<EOL><DEDENT>

Get the earliest visit time of the stop.


to_visit = False<EOL>if event.arr_time_ut <= self.min_transfer_time+self.get_min_visit_time():<EOL><INDENT>to_visit = True<EOL><DEDENT>else:<EOL><INDENT>for ve in self.visit_events:<EOL><INDENT>if (event.trip_I == ve.trip_I) and event.arr_time_ut < ve.arr_time_ut:<EOL><INDENT>to_visit = True<EOL><DEDENT><DEDENT><DEDENT>if to_visit:<EOL><INDENT>self.visit_events.append(event)<EOL>min_time = self.get_min_visit_time()<EOL>self.visit_events = [v for v in self.visit_events if v.arr_time_ut <= min_time+self.min_transfer_time]<EOL><DEDENT>return to_visit<EOL>

Visit the stop if it has not been visited already by an event with
earlier arr_time_ut (or with other trip that does not require a transfer)

Parameters
----------
event : Event
    an instance of the Event (namedtuple)

Returns
-------
visited : bool
    if visit is stored, returns True, otherwise False


if event.from_stop_I != self.stop_I:<EOL><INDENT>return False<EOL><DEDENT>if not self.has_been_visited():<EOL><INDENT>return False<EOL><DEDENT>else:<EOL><INDENT>time_sep = event.dep_time_ut-self.get_min_visit_time()<EOL>if (time_sep >= self.min_transfer_time) or (event.trip_I == -<NUM_LIT:1> and time_sep >= <NUM_LIT:0>):<EOL><INDENT>return True<EOL><DEDENT>else:<EOL><INDENT>for visit in self.visit_events:<EOL><INDENT>if (event.trip_I == visit.trip_I) and (time_sep >= <NUM_LIT:0>):<EOL><INDENT>return True<EOL><DEDENT><DEDENT><DEDENT>return False<EOL><DEDENT>

Whether the spreading stop can infect using this event.


self.heap = []<EOL>keys = ['<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>']<EOL>n = len(pd_df)<EOL>key_to_j = {}<EOL>for j, key in enumerate(pd_df.columns.values):<EOL><INDENT>key_to_j[key] = j<EOL><DEDENT>pd_df_values = pd_df.values<EOL>for i in range(n):<EOL><INDENT>vals = []<EOL>for key in keys:<EOL><INDENT>j = key_to_j[key]<EOL>vals.append(pd_df_values[i, j])<EOL><DEDENT>e = Event(*vals)<EOL>self.add_event(e)<EOL><DEDENT>

Parameters
----------
pd_df : Pandas.Dataframe
    Initial list of


assert event.dep_time_ut <= event.arr_time_ut<EOL>heappush(self.heap, event)<EOL>

Add an event to the heap/priority queue

Parameters
----------
event : Event


return len(self.heap)<EOL>


def add_walk_events_to_heap(self, transfer_distances, e, start_time_ut, walk_speed, uninfected_stops, max_duration_ut):

n = len(transfer_distances)<EOL>dists_values = transfer_distances.values<EOL>to_stop_I_index = np.nonzero(transfer_distances.columns == '<STR_LIT>')[<NUM_LIT:0>][<NUM_LIT:0>]<EOL>d_index = np.nonzero(transfer_distances.columns == '<STR_LIT:d>')[<NUM_LIT:0>][<NUM_LIT:0>]<EOL>for i in range(n):<EOL><INDENT>transfer_to_stop_I = dists_values[i, to_stop_I_index]<EOL>if transfer_to_stop_I in uninfected_stops:<EOL><INDENT>d = dists_values[i, d_index]<EOL>transfer_arr_time = e.arr_time_ut + int(d/float(walk_speed))<EOL>if transfer_arr_time > start_time_ut+max_duration_ut:<EOL><INDENT>continue<EOL><DEDENT>te = Event(transfer_arr_time, e.arr_time_ut, e.to_stop_I, transfer_to_stop_I, WALK)<EOL>self.add_event(te)<EOL><DEDENT><DEDENT>

Parameters
----------
transfer_distances:
e : Event
start_time_ut : int
walk_speed : float
uninfected_stops : list
max_duration_ut : int


def timed(*args, **kw):<EOL><INDENT>time_start = time.time()<EOL>result = method(*args, **kw)<EOL>time_end = time.time()<EOL>print('<STR_LIT>' % (method.__name__, time_end-time_start, str(args)[:<NUM_LIT:20>], kw))<EOL>return result<EOL><DEDENT>return timed<EOL>

A Python decorator for printing out the execution time for a function.

Adapted from:
www.andreas-jung.com/contents/a-python-decorator-for-measuring-the-execution-time-of-methods


assert self._has_run<EOL>return self._run_time<EOL>

Returns
-------
run_time: float
    running time of the algorithm in seconds


if new_pareto_tuple.duration() > self._walk_to_target_duration:<EOL><INDENT>direct_walk_label = self._label_class.direct_walk_label(new_pareto_tuple.departure_time,<EOL>self._walk_to_target_duration)<EOL>if not direct_walk_label.dominates(new_pareto_tuple):<EOL><INDENT>raise<EOL><DEDENT><DEDENT>direct_walk_label = self._label_class.direct_walk_label(new_pareto_tuple.departure_time, self._walk_to_target_duration)<EOL>if direct_walk_label.dominates(new_pareto_tuple):<EOL><INDENT>return False<EOL><DEDENT>if self._new_paretotuple_is_dominated_by_old_tuples(new_pareto_tuple):<EOL><INDENT>return False<EOL><DEDENT>else:<EOL><INDENT>self._remove_old_tuples_dominated_by_new_and_insert_new_paretotuple(new_pareto_tuple)<EOL>return True<EOL><DEDENT>

# this function should be optimized

Parameters
----------
new_pareto_tuple: LabelTimeSimple

Returns
-------
added: bool
    whether new_pareto_tuple was added to the set of pareto-optimal tuples


def evaluate_earliest_arrival_time_at_target(self, dep_time, transfer_margin):

minimum = dep_time + self._walk_to_target_duration<EOL>dep_time_plus_transfer_margin = dep_time + transfer_margin<EOL>for label in self._labels:<EOL><INDENT>if label.departure_time >= dep_time_plus_transfer_margin and label.arrival_time_target < minimum:<EOL><INDENT>minimum = label.arrival_time_target<EOL><DEDENT><DEDENT>return float(minimum)<EOL>

Get the earliest arrival time at the target, given a departure time.

Parameters
----------
dep_time : float, int
    time in unix seconds
transfer_margin: float, int
    transfer margin in seconds

Returns
-------
arrival_time : float
    Arrival time in the given time unit (seconds after unix epoch).


def _truncate_colormap(cmap, minval=<NUM_LIT:0.0>, maxval=<NUM_LIT:1.0>, n=<NUM_LIT:100>):

new_cmap = LinearSegmentedColormap.from_list(<EOL>'<STR_LIT>'.format(n=cmap.name, a=minval, b=maxval),<EOL>cmap(numpy.linspace(minval, maxval, n))<EOL>)<EOL>return new_cmap<EOL>

Truncates a colormap to use.
Code originall from http://stackoverflow.com/questions/18926031/how-to-extract-a-subset-of-a-colormap-as-a-new-colormap-in-matplotlib


def __init__(self, labels, walk_to_target_duration, start_time_dep, end_time_dep):

self._node_profile_final_labels = labels<EOL>self.start_time_dep = start_time_dep<EOL>self.end_time_dep = end_time_dep<EOL>self.all_labels = [label for label in self._node_profile_final_labels if<EOL>(start_time_dep <= label.departure_time <= end_time_dep)]<EOL>after_label_candidates = [label for label in self._node_profile_final_labels if<EOL>(label.departure_time > self.end_time_dep)]<EOL>after_label_candidates.sort(key=lambda el: (el.arrival_time_target, el.n_boardings))<EOL>min_n_boardings_observed = float('<STR_LIT>')<EOL>after_labels = []<EOL>for candidate_after_label in after_label_candidates:<EOL><INDENT>if candidate_after_label.n_boardings < min_n_boardings_observed:<EOL><INDENT>after_labels.append(candidate_after_label)<EOL>min_n_boardings_observed = candidate_after_label.n_boardings<EOL><DEDENT><DEDENT>self.all_labels.extend(after_labels)<EOL>if len(after_labels) is <NUM_LIT:0>:<EOL><INDENT>self._labels_within_time_frame = self.all_labels<EOL><DEDENT>else:<EOL><INDENT>self._labels_within_time_frame = self.all_labels[:-len(after_labels)]<EOL><DEDENT>self._walk_to_target_duration = walk_to_target_duration<EOL>self._n_boardings_to_simple_time_analyzers = {}<EOL>self._transfers_on_fastest_paths_analyzer = self._get_transfers_on_fastest_path_analyzer()<EOL>

Initialize the data structures required by

Parameters
----------
node_profile: NodeProfileMultiObjective


if max_n_boardings is None:<EOL><INDENT>max_n_boardings = self.max_trip_n_boardings()<EOL><DEDENT>if not max_n_boardings in self._n_boardings_to_simple_time_analyzers:<EOL><INDENT>if max_n_boardings == <NUM_LIT:0>:<EOL><INDENT>valids = []<EOL><DEDENT>else:<EOL><INDENT>candidate_labels = [LabelTimeSimple(label.departure_time, label.arrival_time_target)<EOL>for label in self._node_profile_final_labels if<EOL>((self.start_time_dep <= label.departure_time)<EOL>and label.n_boardings <= max_n_boardings)]<EOL>valids = compute_pareto_front(candidate_labels)<EOL><DEDENT>valids.sort(key=lambda label: -label.departure_time)<EOL>profile = NodeProfileSimple(self._walk_to_target_duration)<EOL>for valid in valids:<EOL><INDENT>profile.update_pareto_optimal_tuples(valid)<EOL><DEDENT>npat = NodeProfileAnalyzerTime.from_profile(profile, self.start_time_dep, self.end_time_dep)<EOL>self._n_boardings_to_simple_time_analyzers[max_n_boardings] = npat<EOL><DEDENT>return self._n_boardings_to_simple_time_analyzers[max_n_boardings]<EOL>

Parameters
----------
max_n_boardings: int
    The maximum number of boardings allowed for the labels used to construct the "temporal distance profile"

Returns
-------
analyzer: NodeProfileAnalyzerTime


def median_temporal_distances(self, min_n_boardings=None, max_n_boardings=None):

if min_n_boardings is None:<EOL><INDENT>min_n_boardings = <NUM_LIT:0><EOL><DEDENT>if max_n_boardings is None:<EOL><INDENT>max_n_boardings = self.max_trip_n_boardings()<EOL>if max_n_boardings is None:<EOL><INDENT>max_n_boardings = <NUM_LIT:0><EOL><DEDENT><DEDENT>median_temporal_distances = [float('<STR_LIT>') for _ in range(min_n_boardings, max_n_boardings + <NUM_LIT:1>)]<EOL>for n_boardings in range(min_n_boardings, max_n_boardings + <NUM_LIT:1>):<EOL><INDENT>simple_analyzer = self.get_time_profile_analyzer(n_boardings)<EOL>median_temporal_distances[n_boardings] = simple_analyzer.median_temporal_distance()<EOL><DEDENT>return median_temporal_distances<EOL>

Returns
-------
mean_temporal_distances: list
    list indices encode the number of vehicle legs each element
    in the list tells gets the mean temporal distance


return float(len(self._labels_within_time_frame))<EOL>

Get number of pareto-optimal trips

Returns
-------
n_trips: float


AbstractRoutingAlgorithm.__init__(self)<EOL>assert (len(transit_events) == len(set(transit_events))), "<STR_LIT>"<EOL>self._transit_connections = transit_events<EOL>if start_time_ut is None:<EOL><INDENT>start_time_ut = transit_events[-<NUM_LIT:1>].departure_time<EOL><DEDENT>if end_time_ut is None:<EOL><INDENT>end_time_ut = transit_events[<NUM_LIT:0>].departure_time<EOL><DEDENT>self._start_time = start_time_ut<EOL>self._end_time = end_time_ut<EOL>self._transfer_margin = transfer_margin<EOL>if walk_network is None:<EOL><INDENT>walk_network = networkx.Graph()<EOL><DEDENT>self._walk_network = walk_network<EOL>self._walk_speed = walk_speed<EOL>self._verbose = verbose<EOL>self._count_vehicle_legs = track_vehicle_legs<EOL>self._consider_time = track_time<EOL>assert(track_time or track_vehicle_legs)<EOL>if track_vehicle_legs:<EOL><INDENT>if track_time:<EOL><INDENT>if track_route:<EOL><INDENT>self._label_class = LabelTimeBoardingsAndRoute<EOL><DEDENT>else:<EOL><INDENT>self._label_class = LabelTimeWithBoardingsCount<EOL><DEDENT><DEDENT>else:<EOL><INDENT>self._label_class = LabelVehLegCount<EOL><DEDENT><DEDENT>else:<EOL><INDENT>if track_route:<EOL><INDENT>self._label_class = LabelTimeAndRoute<EOL><DEDENT>else:<EOL><INDENT>self._label_class = LabelTime<EOL><DEDENT><DEDENT>print("<STR_LIT>", str(self._label_class))<EOL>self._stop_departure_times, self._stop_arrival_times = self.__compute_stop_dep_and_arrival_times()<EOL>self._all_nodes = set.union(set(self._stop_departure_times.keys()),<EOL>set(self._stop_arrival_times.keys()),<EOL>set(self._walk_network.nodes()))<EOL>self._pseudo_connections = self.__compute_pseudo_connections()<EOL>self._add_pseudo_connection_departures_to_stop_departure_times()<EOL>self._all_connections = self._pseudo_connections + self._transit_connections<EOL>self._all_connections.sort(key=lambda connection: (-connection.departure_time, -connection.seq))<EOL>self._augment_all_connections_with_arrival_stop_next_dep_time()<EOL>if isinstance(targets, list):<EOL><INDENT>self._targets = targets<EOL><DEDENT>else:<EOL><INDENT>self._targets = [targets]<EOL><DEDENT>self.reset(self._targets)<EOL>

Parameters
----------
transit_events: list[Connection]
    events are assumed to be ordered in DECREASING departure_time (!)
targets: int, list
    index of the target stop
start_time_ut : int, optional
    start time in unixtime seconds
end_time_ut: int, optional
    end time in unixtime seconds (no connections will be scanned after this time)
transfer_margin: int, optional
    required extra margin required for transfers in seconds
walk_speed: float, optional
    walking speed between stops in meters / second.
walk_network: networkx.Graph, optional
    each edge should have the walking distance as a data attribute ("distance_shape") expressed in meters
verbose: boolean, optional
    whether to print out progress
track_vehicle_legs: boolean, optional
    whether to consider the number of vehicle legs
track_time: boolean, optional
    whether to consider time in the set of pareto_optimal