signature:
def _get_warped_array ( input_file = None , indexes = None , dst_bounds = None , dst_shape = None , dst_crs = None , resampling = None , src_nodata = None , dst_nodata = None ) :
    """Extract a numpy array from a raster file ."""

implementation:
try :
    return _rasterio_read ( input_file = input_file , indexes = indexes , dst_bounds = dst_bounds , dst_shape = dst_shape , dst_crs = dst_crs , resampling = resampling , src_nodata = src_nodata , dst_nodata = dst_nodata )
except Exception as e :
    logger . exception ( "error while reading file %s: %s" , input_file , e )
    raise


signature:
def read_raster_no_crs ( input_file , indexes = None , gdal_opts = None ) :
    """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 ."""

implementation:
with warnings . catch_warnings ( ) :
    warnings . simplefilter ( "ignore" )
    try :
        with rasterio . Env ( ** get_gdal_options ( gdal_opts , is_remote = path_is_remote ( input_file , s3 = True ) ) ) :
            with rasterio . open ( input_file , "r" ) as src :
                return src . read ( indexes = indexes , masked = True )
    except RasterioIOError as e :
        for i in ( "does not exist in the file system" , "No such file or directory" ) :
            if i in str ( e ) :
                raise FileNotFoundError ( "%s not found" % input_file )
        else :
            raise


signature:
def write_raster_window ( in_tile = None , in_data = None , out_profile = None , out_tile = None , out_path = None , tags = None , bucket_resource = None ) :
    """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"""

implementation:
if not isinstance ( out_path , str ) :
    raise TypeError ( "out_path must be a string" )
logger . debug ( "write %s" , out_path )
if out_path == "memoryfile" :
    raise DeprecationWarning ( "Writing to memoryfile with write_raster_window() is deprecated. " "Please use RasterWindowMemoryFile." )
out_tile = in_tile if out_tile is None else out_tile
_validate_write_window_params ( in_tile , out_tile , in_data , out_profile )
# extract data
window_data = extract_from_array ( in_raster = in_data , in_affine = in_tile . affine , out_tile = out_tile ) if in_tile != out_tile else in_data
# use transform instead of affine
if "affine" in out_profile :
    out_profile [ "transform" ] = out_profile . pop ( "affine" )
# write if there is any band with non - masked data
if window_data . all ( ) is not ma . masked :
    try :
        if out_path . startswith ( "s3://" ) :
            with RasterWindowMemoryFile ( in_tile = out_tile , in_data = window_data , out_profile = out_profile , out_tile = out_tile , tags = tags ) as memfile :
                logger . debug ( ( out_tile . id , "upload tile" , out_path ) )
                bucket_resource . put_object ( Key = "/" . join ( out_path . split ( "/" ) [ 3 : ] ) , Body = memfile )
        else :
            with rasterio . open ( out_path , 'w' , ** out_profile ) as dst :
                logger . debug ( ( out_tile . id , "write tile" , out_path ) )
                dst . write ( window_data . astype ( out_profile [ "dtype" ] , copy = False ) )
                _write_tags ( dst , tags )
    except Exception as e :
        logger . exception ( "error while writing file %s: %s" , out_path , e )
        raise
else :
    logger . debug ( ( out_tile . id , "array window empty" , out_path ) )


signature:
def extract_from_array ( in_raster = None , in_affine = None , out_tile = None ) :
    """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"""

implementation:
if isinstance ( in_raster , ReferencedRaster ) :
    in_affine = in_raster . affine
    in_raster = in_raster . data
# get range within array
minrow , maxrow , mincol , maxcol = bounds_to_ranges ( out_bounds = out_tile . bounds , in_affine = in_affine , in_shape = in_raster . shape )
# if output window is within input window
if ( minrow >= 0 and mincol >= 0 and maxrow <= in_raster . shape [ - 2 ] and maxcol <= in_raster . shape [ - 1 ] ) :
    return in_raster [ ... , minrow : maxrow , mincol : maxcol ]
# raise error if output is not fully within input
else :
    raise ValueError ( "extraction fails if output shape is not within input" )


signature:
def resample_from_array ( in_raster = None , in_affine = None , out_tile = None , in_crs = None , resampling = "nearest" , nodataval = 0 ) :
    """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"""

implementation:
# TODO rename function
if isinstance ( in_raster , ma . MaskedArray ) :
    pass
if isinstance ( in_raster , np . ndarray ) :
    in_raster = ma . MaskedArray ( in_raster , mask = in_raster == nodataval )
elif isinstance ( in_raster , ReferencedRaster ) :
    in_affine = in_raster . affine
    in_crs = in_raster . crs
    in_raster = in_raster . data
elif isinstance ( in_raster , tuple ) :
    in_raster = ma . MaskedArray ( data = np . stack ( in_raster ) , mask = np . stack ( [ band . mask if isinstance ( band , ma . masked_array ) else np . where ( band == nodataval , True , False ) for band in in_raster ] ) , fill_value = nodataval )
else :
    raise TypeError ( "wrong input data type: %s" % type ( in_raster ) )
if in_raster . ndim == 2 :
    in_raster = ma . expand_dims ( in_raster , axis = 0 )
elif in_raster . ndim == 3 :
    pass
else :
    raise TypeError ( "input array must have 2 or 3 dimensions" )
if in_raster . fill_value != nodataval :
    ma . set_fill_value ( in_raster , nodataval )
out_shape = ( in_raster . shape [ 0 ] , ) + out_tile . shape
dst_data = np . empty ( out_shape , in_raster . dtype )
in_raster = ma . masked_array ( data = in_raster . filled ( ) , mask = in_raster . mask , fill_value = nodataval )
reproject ( in_raster , dst_data , src_transform = in_affine , src_crs = in_crs if in_crs else out_tile . crs , dst_transform = out_tile . affine , dst_crs = out_tile . crs , resampling = Resampling [ resampling ] )
return ma . MaskedArray ( dst_data , mask = dst_data == nodataval )


signature:
def create_mosaic ( tiles , nodata = 0 ) :
    """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"""

implementation:
if isinstance ( tiles , GeneratorType ) :
    tiles = list ( tiles )
elif not isinstance ( tiles , list ) :
    raise TypeError ( "tiles must be either a list or generator" )
if not all ( [ isinstance ( pair , tuple ) for pair in tiles ] ) :
    raise TypeError ( "tiles items must be tuples" )
if not all ( [ all ( [ isinstance ( tile , BufferedTile ) , isinstance ( data , np . ndarray ) ] ) for tile , data in tiles ] ) :
    raise TypeError ( "tuples must be pairs of BufferedTile and array" )
if len ( tiles ) == 0 :
    raise ValueError ( "tiles list is empty" )
logger . debug ( "create mosaic from %s tile(s)" , len ( tiles ) )
# quick return if there is just one tile
if len ( tiles ) == 1 :
    tile , data = tiles [ 0 ]
    return ReferencedRaster ( data = data , affine = tile . affine , bounds = tile . bounds , crs = tile . crs )
# assert all tiles have same properties
pyramid , resolution , dtype = _get_tiles_properties ( tiles )
# just handle antimeridian on global pyramid types
shift = _shift_required ( tiles )
# determine mosaic shape and reference
m_left , m_bottom , m_right , m_top = None , None , None , None
for tile , data in tiles :
    num_bands = data . shape [ 0 ] if data . ndim > 2 else 1
    left , bottom , right , top = tile . bounds
    if shift : # shift by half of the grid width
        left += pyramid . x_size / 2
        right += pyramid . x_size / 2
        # if tile is now shifted outside pyramid bounds , move within
        if right > pyramid . right :
            right -= pyramid . x_size
            left -= pyramid . x_size
    m_left = min ( [ left , m_left ] ) if m_left is not None else left
    m_bottom = min ( [ bottom , m_bottom ] ) if m_bottom is not None else bottom
    m_right = max ( [ right , m_right ] ) if m_right is not None else right
    m_top = max ( [ top , m_top ] ) if m_top is not None else top
height = int ( round ( ( m_top - m_bottom ) / resolution ) )
width = int ( round ( ( m_right - m_left ) / resolution ) )
# initialize empty mosaic
mosaic = ma . MaskedArray ( data = np . full ( ( num_bands , height , width ) , dtype = dtype , fill_value = nodata ) , mask = np . ones ( ( num_bands , height , width ) ) )
# create Affine
affine = Affine ( resolution , 0 , m_left , 0 , - resolution , m_top )
# fill mosaic array with tile data
for tile , data in tiles :
    data = prepare_array ( data , nodata = nodata , dtype = dtype )
    t_left , t_bottom , t_right , t_top = tile . bounds
    if shift :
        t_left += pyramid . x_size / 2
        t_right += pyramid . x_size / 2
        # if tile is now shifted outside pyramid bounds , move within
        if t_right > pyramid . right :
            t_right -= pyramid . x_size
            t_left -= pyramid . x_size
    minrow , maxrow , mincol , maxcol = bounds_to_ranges ( out_bounds = ( t_left , t_bottom , t_right , t_top ) , in_affine = affine , in_shape = ( height , width ) )
    mosaic [ : , minrow : maxrow , mincol : maxcol ] = data
    mosaic . mask [ : , minrow : maxrow , mincol : maxcol ] = data . mask
if shift : # shift back output mosaic
    affine = Affine ( resolution , 0 , m_left - pyramid . x_size / 2 , 0 , - resolution , m_top )
return ReferencedRaster ( data = mosaic , affine = affine , bounds = Bounds ( m_left , m_bottom , m_right , m_top ) , crs = tile . crs )


signature:
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"""

implementation: return itertools . chain ( * from_bounds ( * out_bounds , transform = in_affine , height = in_shape [ - 2 ] , width = in_shape [ - 1 ] ) . round_lengths ( pixel_precision = 0 ) . round_offsets ( pixel_precision = 0 ) . toranges ( ) )


signature:
def tiles_to_affine_shape ( tiles ) :
    """Return Affine and shape of combined tiles .
 Parameters
 tiles : iterable
 an iterable containing BufferedTiles
 Returns
 Affine , Shape"""

implementation:
if not tiles :
    raise TypeError ( "no tiles provided" )
pixel_size = tiles [ 0 ] . pixel_x_size
left , bottom , right , top = ( min ( [ t . left for t in tiles ] ) , min ( [ t . bottom for t in tiles ] ) , max ( [ t . right for t in tiles ] ) , max ( [ t . top for t in tiles ] ) , )
return ( Affine ( pixel_size , 0 , left , 0 , - pixel_size , top ) , Shape ( width = int ( round ( ( right - left ) / pixel_size , 0 ) ) , height = int ( round ( ( top - bottom ) / pixel_size , 0 ) ) , ) )


signature:
def memory_file ( data = None , profile = None ) :
    """Return a rasterio . io . MemoryFile instance from input .
 Parameters
 data : array
 array to be written
 profile : dict
 rasterio profile for MemoryFile"""

implementation:
memfile = MemoryFile ( )
profile . update ( width = data . shape [ - 2 ] , height = data . shape [ - 1 ] )
with memfile . open ( ** profile ) as dataset :
    dataset . write ( data )
return memfile


signature:
def prepare_array ( data , masked = True , nodata = 0 , dtype = "int16" ) :
    """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"""

implementation:
# input is iterable
if isinstance ( data , ( list , tuple ) ) :
    return _prepare_iterable ( data , masked , nodata , dtype )
# special case if a 2D single band is provided
elif isinstance ( data , np . ndarray ) and data . ndim == 2 :
    data = ma . expand_dims ( data , axis = 0 )
# input is a masked array
if isinstance ( data , ma . MaskedArray ) :
    return _prepare_masked ( data , masked , nodata , dtype )
# input is a NumPy array
elif isinstance ( data , np . ndarray ) :
    if masked :
        return ma . masked_values ( data . astype ( dtype , copy = False ) , nodata , copy = False )
    else :
        return data . astype ( dtype , copy = False )
else :
    raise ValueError ( "data must be array, masked array or iterable containing arrays." )


signature:
def bbox ( self , out_crs = None ) :
    """Return data bounding box .
 Parameters
 out _ crs : ` ` rasterio . crs . CRS ` `
 rasterio CRS object ( default : CRS of process pyramid )
 Returns
 bounding box : geometry
 Shapely geometry object"""

implementation:
out_crs = self . pyramid . crs if out_crs is None else out_crs
with fiona . open ( self . path ) as inp :
    inp_crs = CRS ( inp . crs )
    bbox = box ( * inp . bounds )
# TODO find a way to get a good segmentize value in bbox source CRS
return reproject_geometry ( bbox , src_crs = inp_crs , dst_crs = out_crs )


signature:
def read ( self , validity_check = True , ** kwargs ) :
    """Read reprojected & resampled input data .
 Parameters
 validity _ check : bool
 also run checks if reprojected geometry is valid , otherwise throw
 RuntimeError ( default : True )
 Returns
 data : list"""

implementation: return [ ] if self . is_empty ( ) else self . _read_from_cache ( validity_check )


signature:
def is_empty ( self ) :
    """Check if there is data within this tile .
 Returns
 is empty : bool"""

implementation:
if not self . tile . bbox . intersects ( self . vector_file . bbox ( ) ) :
    return True
return len ( self . _read_from_cache ( True ) ) == 0


signature:
def reproject_geometry ( geometry , src_crs = None , dst_crs = None , error_on_clip = False , validity_check = True , antimeridian_cutting = False ) :
    """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 ` `"""

implementation:
src_crs = _validated_crs ( src_crs )
dst_crs = _validated_crs ( dst_crs )
def _reproject_geom ( geometry , src_crs , dst_crs ) :
    if geometry . is_empty :
        return geometry
    else :
        out_geom = to_shape ( transform_geom ( src_crs . to_dict ( ) , dst_crs . to_dict ( ) , mapping ( geometry ) , antimeridian_cutting = antimeridian_cutting ) )
        return _repair ( out_geom ) if validity_check else out_geom
# return repaired geometry if no reprojection needed
if src_crs == dst_crs or geometry . is_empty :
    return _repair ( geometry )
# geometry needs to be clipped to its CRS bounds
elif ( dst_crs . is_epsg_code and # just in case for an CRS with EPSG code
dst_crs . get ( "init" ) in CRS_BOUNDS and # if CRS has defined bounds
dst_crs . get ( "init" ) != "epsg:4326" # and is not WGS84 ( does not need clipping )
) :
    wgs84_crs = CRS ( ) . from_epsg ( 4326 )
    # get dst _ crs boundaries
    crs_bbox = box ( * CRS_BOUNDS [ dst_crs . get ( "init" ) ] )
    # reproject geometry to WGS84
    geometry_4326 = _reproject_geom ( geometry , src_crs , wgs84_crs )
    # raise error if geometry has to be clipped
    if error_on_clip and not geometry_4326 . within ( crs_bbox ) :
        raise RuntimeError ( "geometry outside target CRS bounds" )
    # clip geometry dst _ crs boundaries and return
    return _reproject_geom ( crs_bbox . intersection ( geometry_4326 ) , wgs84_crs , dst_crs )
# return without clipping if destination CRS does not have defined bounds
else :
    return _reproject_geom ( geometry , src_crs , dst_crs )


signature:
def segmentize_geometry ( geometry , segmentize_value ) :
    """Segmentize Polygon outer ring by segmentize value .
 Just Polygon geometry type supported .
 Parameters
 geometry : ` ` shapely . geometry ` `
 segmentize _ value : float
 Returns
 geometry : ` ` shapely . geometry ` `"""

implementation:
if geometry . geom_type != "Polygon" :
    raise TypeError ( "segmentize geometry type must be Polygon" )
return Polygon ( LinearRing ( [ p # pick polygon linestrings
for l in map ( lambda x : LineString ( [ x [ 0 ] , x [ 1 ] ] ) , zip ( geometry . exterior . coords [ : - 1 ] , geometry . exterior . coords [ 1 : ] ) ) # interpolate additional points in between and don ' t forget end point
for p in [ l . interpolate ( segmentize_value * i ) . coords [ 0 ] for i in range ( int ( l . length / segmentize_value ) ) ] + [ l . coords [ 1 ] ] ] ) )


signature:
def read_vector_window ( input_files , tile , validity_check = True ) :
    """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"""

implementation:
if not isinstance ( input_files , list ) :
    input_files = [ input_files ]
return [ feature for feature in chain . from_iterable ( [ _read_vector_window ( path , tile , validity_check = validity_check ) for path in input_files ] ) ]


signature:
def write_vector_window ( in_data = None , out_schema = None , out_tile = None , out_path = None , bucket_resource = None ) :
    """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"""

implementation:
# Delete existing file .
try :
    os . remove ( out_path )
except OSError :
    pass
out_features = [ ]
for feature in in_data :
    try : # clip feature geometry to tile bounding box and append for writing
    # if clipped feature still
        for out_geom in multipart_to_singleparts ( clean_geometry_type ( to_shape ( feature [ "geometry" ] ) . intersection ( out_tile . bbox ) , out_schema [ "geometry" ] ) ) :
            out_features . append ( { "geometry" : mapping ( out_geom ) , "properties" : feature [ "properties" ] } )
    except Exception as e :
        logger . warning ( "failed to prepare geometry for writing: %s" , e )
        continue
# write if there are output features
if out_features :
    try :
        if out_path . startswith ( "s3://" ) : # write data to remote file
            with VectorWindowMemoryFile ( tile = out_tile , features = out_features , schema = out_schema , driver = "GeoJSON" ) as memfile :
                logger . debug ( ( out_tile . id , "upload tile" , out_path ) )
                bucket_resource . put_object ( Key = "/" . join ( out_path . split ( "/" ) [ 3 : ] ) , Body = memfile )
        else : # write data to local file
            with fiona . open ( out_path , 'w' , schema = out_schema , driver = "GeoJSON" , crs = out_tile . crs . to_dict ( ) ) as dst :
                logger . debug ( ( out_tile . id , "write tile" , out_path ) )
                dst . writerecords ( out_features )
    except Exception as e :
        logger . error ( "error while writing file %s: %s" , out_path , e )
        raise
else :
    logger . debug ( ( out_tile . id , "nothing to write" , out_path ) )


signature:
def clean_geometry_type ( geometry , target_type , allow_multipart = True ) :
    """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"""

implementation:
multipart_geoms = { "Point" : MultiPoint , "LineString" : MultiLineString , "Polygon" : MultiPolygon , "MultiPoint" : MultiPoint , "MultiLineString" : MultiLineString , "MultiPolygon" : MultiPolygon }
if target_type not in multipart_geoms . keys ( ) :
    raise TypeError ( "target type is not supported: %s" % target_type )
if geometry . geom_type == target_type :
    return geometry
elif allow_multipart :
    target_multipart_type = multipart_geoms [ target_type ]
    if geometry . geom_type == "GeometryCollection" :
        return target_multipart_type ( [ clean_geometry_type ( g , target_type , allow_multipart ) for g in geometry ] )
    elif any ( [ isinstance ( geometry , target_multipart_type ) , multipart_geoms [ geometry . geom_type ] == target_multipart_type ] ) :
        return geometry
raise GeometryTypeError ( "geometry type does not match: %s, %s" % ( geometry . geom_type , target_type ) )


signature:
def multipart_to_singleparts ( geom ) :
    """Yield single part geometries if geom is multipart , otherwise yield geom .
 Parameters :
 geom : shapely geometry
 Returns :
 shapely single part geometries"""

implementation:
if isinstance ( geom , base . BaseGeometry ) :
    if hasattr ( geom , "geoms" ) :
        for subgeom in geom :
            yield subgeom
    else :
        yield geom


signature:
def execute ( mp , td_resampling = "nearest" , td_matching_method = "gdal" , td_matching_max_zoom = None , td_matching_precision = 8 , td_fallback_to_higher_zoom = False , clip_pixelbuffer = 0 , ** kwargs ) :
    """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"""

implementation:
# read clip geometry
if "clip" in mp . params [ "input" ] :
    clip_geom = mp . open ( "clip" ) . read ( )
    if not clip_geom :
        logger . debug ( "no clip data over tile" )
        return "empty"
else :
    clip_geom = [ ]
with mp . open ( "raster" , matching_method = td_matching_method , matching_max_zoom = td_matching_max_zoom , matching_precision = td_matching_precision , fallback_to_higher_zoom = td_fallback_to_higher_zoom , resampling = td_resampling ) as raster :
    raster_data = raster . read ( )
    if raster . is_empty ( ) or raster_data [ 0 ] . mask . all ( ) :
        logger . debug ( "raster empty" )
        return "empty"
if clip_geom : # apply original nodata mask and clip
    clipped = mp . clip ( np . where ( raster_data [ 0 ] . mask , mp . params [ "output" ] . nodata , raster_data ) , clip_geom , clip_buffer = clip_pixelbuffer , inverted = True )
    return np . where ( clipped . mask , clipped , mp . params [ "output" ] . nodata )
else :
    return np . where ( raster_data [ 0 ] . mask , mp . params [ "output" ] . nodata , raster_data )


signature:
def get_best_zoom_level ( input_file , tile_pyramid_type ) :
    """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"""

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


signature:
def get_segmentize_value ( input_file = None , tile_pyramid = None ) :
    """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"""

implementation:
with rasterio . open ( input_file , "r" ) as input_raster :
    pixelsize = input_raster . transform [ 0 ]
return pixelsize * tile_pyramid . tile_size


signature:
def tile_to_zoom_level ( tile , dst_pyramid = None , matching_method = "gdal" , precision = 8 ) :
    """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"""

implementation:
def width_height ( bounds ) :
    try :
        l , b , r , t = reproject_geometry ( box ( * bounds ) , src_crs = tile . crs , dst_crs = dst_pyramid . crs ) . bounds
    except ValueError :
        raise TopologicalError ( "bounds cannot be translated into target CRS" )
    return r - l , t - b
if tile . tp . crs == dst_pyramid . crs :
    return tile . zoom
else :
    if matching_method == "gdal" : # use rasterio / GDAL method to calculate default warp target properties
        transform , width , height = calculate_default_transform ( tile . tp . crs , dst_pyramid . crs , tile . width , tile . height , * tile . bounds )
        # this is the resolution the tile would have in destination TilePyramid CRS
        tile_resolution = round ( transform [ 0 ] , precision )
    elif matching_method == "min" : # calculate the minimum pixel size from the four tile corner pixels
        l , b , r , t = tile . bounds
        x = tile . pixel_x_size
        y = tile . pixel_y_size
        res = [ ]
        for bounds in [ ( l , t - y , l + x , t ) , # left top
        ( l , b , l + x , b + y ) , # left bottom
        ( r - x , b , r , b + y ) , # right bottom
        ( r - x , t - y , r , t ) # right top
        ] :
            try :
                w , h = width_height ( bounds )
                res . extend ( [ w , h ] )
            except TopologicalError :
                logger . debug ( "pixel outside of destination pyramid" )
        if res :
            tile_resolution = round ( min ( res ) , precision )
        else :
            raise TopologicalError ( "tile outside of destination pyramid" )
    else :
        raise ValueError ( "invalid method given: %s" , matching_method )
    logger . debug ( "we are looking for a zoom level interpolating to %s resolution" , tile_resolution )
    zoom = 0
    while True :
        td_resolution = round ( dst_pyramid . pixel_x_size ( zoom ) , precision )
        if td_resolution <= tile_resolution :
            break
        zoom += 1
    logger . debug ( "target zoom for %s: %s (%s)" , tile_resolution , zoom , td_resolution )
    return zoom


signature:
def path_is_remote ( path , s3 = True ) :
    """Determine whether file path is remote or local .
 Parameters
 path : path to file
 Returns
 is _ remote : bool"""

implementation:
prefixes = ( "http://" , "https://" , "/vsicurl/" )
if s3 :
    prefixes += ( "s3://" , "/vsis3/" )
return path . startswith ( prefixes )


signature:
def path_exists ( path ) :
    """Check if file exists either remote or local .
 Parameters :
 path : path to file
 Returns :
 exists : bool"""

implementation:
if path . startswith ( ( "http://" , "https://" ) ) :
    try :
        urlopen ( path ) . info ( )
        return True
    except HTTPError as e :
        if e . code == 404 :
            return False
        else :
            raise
elif path . startswith ( "s3://" ) :
    bucket = get_boto3_bucket ( path . split ( "/" ) [ 2 ] )
    key = "/" . join ( path . split ( "/" ) [ 3 : ] )
    for obj in bucket . objects . filter ( Prefix = key ) :
        if obj . key == key :
            return True
    else :
        return False
else :
    logger . debug ( "%s exists: %s" , path , os . path . exists ( path ) )
    return os . path . exists ( path )


signature:
def absolute_path ( path = None , base_dir = None ) :
    """Return absolute path if path is local .
 Parameters :
 path : path to file
 base _ dir : base directory used for absolute path
 Returns :
 absolute path"""

implementation:
if path_is_remote ( path ) :
    return path
else :
    if os . path . isabs ( path ) :
        return path
    else :
        if base_dir is None or not os . path . isabs ( base_dir ) :
            raise TypeError ( "base_dir must be an absolute path." )
        return os . path . abspath ( os . path . join ( base_dir , path ) )


signature:
def relative_path ( path = None , base_dir = None ) :
    """Return relative path if path is local .
 Parameters :
 path : path to file
 base _ dir : directory where path sould be relative to
 Returns :
 relative path"""

implementation:
if path_is_remote ( path ) or not os . path . isabs ( path ) :
    return path
else :
    return os . path . relpath ( path , base_dir )


signature:
def write_json ( path , params ) :
    """Write local or remote ."""

implementation:
logger . debug ( "write %s to %s" , params , path )
if path . startswith ( "s3://" ) :
    bucket = get_boto3_bucket ( path . split ( "/" ) [ 2 ] )
    key = "/" . join ( path . split ( "/" ) [ 3 : ] )
    logger . debug ( "upload %s" , key )
    bucket . put_object ( Key = key , Body = json . dumps ( params , sort_keys = True , indent = 4 ) )
else :
    makedirs ( os . path . dirname ( path ) )
    with open ( path , 'w' ) as dst :
        json . dump ( params , dst , sort_keys = True , indent = 4 )


signature:
def read_json ( path ) :
    """Read local or remote ."""

implementation:
if path . startswith ( ( "http://" , "https://" ) ) :
    try :
        return json . loads ( urlopen ( path ) . read ( ) . decode ( ) )
    except HTTPError :
        raise FileNotFoundError ( "%s not found" , path )
elif path . startswith ( "s3://" ) :
    bucket = get_boto3_bucket ( path . split ( "/" ) [ 2 ] )
    key = "/" . join ( path . split ( "/" ) [ 3 : ] )
    for obj in bucket . objects . filter ( Prefix = key ) :
        if obj . key == key :
            return json . loads ( obj . get ( ) [ 'Body' ] . read ( ) . decode ( ) )
    raise FileNotFoundError ( "%s not found" , path )
else :
    try :
        with open ( path , "r" ) as src :
            return json . loads ( src . read ( ) )
    except :
        raise FileNotFoundError ( "%s not found" , path )


signature:
def get_gdal_options ( opts , is_remote = False ) :
    """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"""

implementation:
user_opts = { } if opts is None else dict ( ** opts )
if is_remote :
    return dict ( GDAL_HTTP_OPTS , ** user_opts )
else :
    return user_opts


signature:
def open ( self , tile , ** kwargs ) :
    """Return InputTile object .
 Parameters
 tile : ` ` Tile ` `
 Returns
 input tile : ` ` InputTile ` `
 tile view of input data"""

implementation: return self . process . config . output . open ( tile , self . process , ** kwargs )


signature:
def bbox ( self , out_crs = None ) :
    """Return data bounding box .
 Parameters
 out _ crs : ` ` rasterio . crs . CRS ` `
 rasterio CRS object ( default : CRS of process pyramid )
 Returns
 bounding box : geometry
 Shapely geometry object"""

implementation: return reproject_geometry ( self . process . config . area_at_zoom ( ) , src_crs = self . process . config . process_pyramid . crs , dst_crs = self . pyramid . crs if out_crs is None else out_crs )


signature:
def win_activate ( title , ** kwargs ) :
    """Activates ( gives focus to ) a window .
 : param title :
 : param text :
 : return :"""

implementation:
text = kwargs . get ( "text" , "" )
ret = AUTO_IT . AU3_WinActivate ( LPCWSTR ( title ) , LPCWSTR ( text ) )
return ret


signature:
def win_exists ( title , ** kwargs ) :
    """Checks to see if a specified window exists .
 : param title : The title of the window to check .
 : param text : The text of the window to check .
 : return : Returns 1 if the window exists , otherwise returns 0."""

implementation:
text = kwargs . get ( "text" , "" )
ret = AUTO_IT . AU3_WinExists ( LPCWSTR ( title ) , LPCWSTR ( text ) )
return ret


signature:
def win_get_caret_pos ( ) :
    """Returns the coordinates of the caret in the foreground window
 : return :"""

implementation:
p = POINT ( )
AUTO_IT . AU3_WinGetCaretPos ( byref ( p ) )
return p . x , p . y


signature:
def win_get_state ( title , ** kwargs ) :
    """Retrieves the state of a given window .
 : param title :
 : param text :
 : return :
 1 = Window exists
 2 = Window is visible
 4 = Windows is enabled
 8 = Window is active
 16 = Window is minimized
 32 = Windows is maximized"""

implementation:
text = kwargs . get ( "text" , "" )
res = AUTO_IT . AU3_WinGetState ( LPCWSTR ( title ) , LPCWSTR ( text ) )
return res


signature:
def win_menu_select_item ( title , * items , ** kwargs ) :
    """Usage :
 win _ menu _ select _ item ( " [ CLASS : Notepad ] " , " " , u " 文件 ( & F ) " , u " 退出 ( & X ) " )
 : param title :
 : param text :
 : param items :
 : return :"""

implementation:
text = kwargs . get ( "text" , "" )
if not ( 0 < len ( items ) < 8 ) :
    raise ValueError ( "accepted none item or number of items exceed eight" )
f_items = [ LPCWSTR ( item ) for item in items ]
for i in xrange ( 8 - len ( f_items ) ) :
    f_items . append ( LPCWSTR ( "" ) )
ret = AUTO_IT . AU3_WinMenuSelectItem ( LPCWSTR ( title ) , LPCWSTR ( text ) , * f_items )
return ret


signature:
def win_set_trans ( title , trans , ** kwargs ) :
    """Sets the transparency of a window .
 : param title :
 : param trans : A number in the range 0 - 255 . The larger the number ,
 the more transparent the window will become .
 : param kwargs :
 : return :"""

implementation:
text = kwargs . get ( "text" , "" )
ret = AUTO_IT . AU3_WinSetTrans ( LPCWSTR ( title ) , LPCWSTR ( text ) , INT ( trans ) )
return ret


signature:
def auto_it_set_option ( option , param ) :
    """Changes the operation of various AutoIt functions / parameters
 : param option : The option to change
 : param param : The parameter ( varies by option ) .
 : return :"""

implementation:
pre_value = AUTO_IT . AU3_AutoItSetOption ( LPCWSTR ( option ) , INT ( param ) )
return pre_value


signature:
def check ( self , mark = 0 , err_msg = "" , ** kwds ) :
    """: param mark :
 0 - do not need check return value or error ( )
 1 - check error ( )
 2 - check return value"""

implementation:
unexpected_ret = kwds . get ( "unexpected_ret" , ( 0 , ) )
def _check ( fn ) :
    @ wraps ( fn )
    def wrapper ( * args , ** kwargs ) :
        ret = fn ( * args , ** kwargs )
        flags = reduce ( self . _parser , [ dict ( num = mark , flags = [ ] ) , 2 , 1 ] ) [ "flags" ]
        if 1 in flags :
            if self . _has_error ( ) :
                raise AutoItError ( err_msg )
        if 2 in flags :
            if self . _has_unexpected_ret ( ret , unexpected_ret ) :
                raise AutoItError ( err_msg )
        return ret
    return wrapper
return _check


signature:
def process_set_priority ( process , priority ) :
    """Changes the priority of a process
 : param process : The name or PID of the process to check .
 : param priority : A flag which determines what priority to set
 0 - Idle / Low
 1 - Below Normal ( Not supported on Windows 95/98 / ME )
 2 - Normal
 3 - Above Normal ( Not supported on Windows 95/98 / ME )
 4 - High
 5 - Realtime ( Use with caution , may make the system unstable )
 : return :"""

implementation:
ret = AUTO_IT . AU3_ProcessSetPriority ( LPCWSTR ( process ) , INT ( priority ) )
if ret == 0 :
    if error ( ) == 1 :
        raise AutoItError ( "set priority failed" )
    elif error ( ) == 2 :
        raise AutoItError ( "unsupported priority class be used" )
return ret


signature:
def process_wait ( process , timeout = 0 ) :
    """Pauses script execution until a given process exists .
 : param process :
 : param timeout :
 : return :"""

implementation:
ret = AUTO_IT . AU3_ProcessWait ( LPCWSTR ( process ) , INT ( timeout ) )
return ret


signature:
def process_wait_close ( process , timeout = 0 ) :
    """Pauses script execution until a given process does not exist .
 : param process :
 : param timeout :
 : return :"""

implementation:
ret = AUTO_IT . AU3_ProcessWaitClose ( LPCWSTR ( process ) , INT ( timeout ) )
return ret


signature:
def run_as ( user , domain , password , filename , logon_flag = 1 , work_dir = "" , show_flag = Properties . SW_SHOWNORMAL ) :
    """Runs an external program .
 : param user : username The user name to use .
 : param domain : The domain name to use .
 : param password : The password to use .
 : param logon _ flag : 0 = do not load the user profile , 1 = ( default ) load
 the user profile , 2 = use for net credentials only
 : param filename : The name of the executable ( EXE , BAT , COM , or PIF ) to run .
 : param work _ dir : The working directory .
 : param show _ flag : The " show " flag of the executed program :
 SW _ HIDE = Hidden window
 SW _ MINIMIZE = Minimized window
 SW _ MAXIMIZE = Maximized window
 : return :"""

implementation:
ret = AUTO_IT . AU3_RunAs ( LPCWSTR ( user ) , LPCWSTR ( domain ) , LPCWSTR ( password ) , INT ( logon_flag ) , LPCWSTR ( filename ) , LPCWSTR ( work_dir ) , INT ( show_flag ) )
return ret


signature:
def run_as_wait ( user , domain , password , filename , logon_flag = 1 , work_dir = "" , show_flag = Properties . SW_SHOWNORMAL ) :
    """Runs an external program .
 : param user : username The user name to use .
 : param domain : The domain name to use .
 : param password : The password to use .
 : param logon _ flag : 0 = do not load the user profile , 1 = ( default ) load
 the user profile , 2 = use for net credentials only
 : param filename : The name of the executable ( EXE , BAT , COM , or PIF ) to run .
 : param work _ dir : The working directory .
 : param show _ flag : The " show " flag of the executed program :
 SW _ HIDE = Hidden window
 SW _ MINIMIZE = Minimized window
 SW _ MAXIMIZE = Maximized window
 : return :"""

implementation:
ret = AUTO_IT . AU3_RunAsWait ( LPCWSTR ( user ) , LPCWSTR ( domain ) , LPCWSTR ( password ) , INT ( logon_flag ) , LPCWSTR ( filename ) , LPCWSTR ( work_dir ) , INT ( show_flag ) )
return ret


signature:
def hook ( self , event_type = 'push' ) :
    """Registers a function as a hook . Multiple hooks can be registered for a given type , but the
 order in which they are invoke is unspecified .
 : param event _ type : The event type this hook will be invoked for ."""

implementation:
def decorator ( func ) :
    self . _hooks [ event_type ] . append ( func )
    return func
return decorator


signature:
def _get_digest ( self ) :
    """Return message digest if a secret key was provided"""

implementation: return hmac . new ( self . _secret , request . data , hashlib . sha1 ) . hexdigest ( ) if self . _secret else None


signature:
def _postreceive ( self ) :
    """Callback from Flask"""

implementation:
digest = self . _get_digest ( )
if digest is not None :
    sig_parts = _get_header ( 'X-Hub-Signature' ) . split ( '=' , 1 )
    if not isinstance ( digest , six . text_type ) :
        digest = six . text_type ( digest )
    if ( len ( sig_parts ) < 2 or sig_parts [ 0 ] != 'sha1' or not hmac . compare_digest ( sig_parts [ 1 ] , digest ) ) :
        abort ( 400 , 'Invalid signature' )
event_type = _get_header ( 'X-Github-Event' )
data = request . get_json ( )
if data is None :
    abort ( 400 , 'Request body must contain json' )
self . _logger . info ( '%s (%s)' , _format_event ( event_type , data ) , _get_header ( 'X-Github-Delivery' ) )
for hook in self . _hooks . get ( event_type , [ ] ) :
    hook ( data )
return '' , 204


signature:
def long_description ( ) :
    """Generate . rst document for PyPi ."""

implementation:
import argparse
parser = argparse . ArgumentParser ( )
parser . add_argument ( '--doc' , dest = "doc" , action = "store_true" , default = False )
args , sys . argv = parser . parse_known_args ( sys . argv )
if args . doc :
    import doc2md , pypandoc
    md = doc2md . doc2md ( doc2md . __doc__ , "doc2md" , toc = False )
    long_description = pypandoc . convert ( md , 'rst' , format = 'md' )
else :
    return None


signature:
def unindent ( lines ) :
    """Remove common indentation from string .
 Unlike doctrim there is no special treatment of the first line ."""

implementation:
try : # Determine minimum indentation :
    indent = min ( len ( line ) - len ( line . lstrip ( ) ) for line in lines if line )
except ValueError :
    return lines
else :
    return [ line [ indent : ] for line in lines ]


signature:
def find_sections ( lines ) :
    """Find all section names and return a list with their names ."""

implementation:
sections = [ ]
for line in lines :
    if is_heading ( line ) :
        sections . append ( get_heading ( line ) )
return sections


signature:
def make_toc ( sections , maxdepth = 0 ) :
    """Generate table of contents for array of section names ."""

implementation:
if not sections :
    return [ ]
outer = min ( n for n , t in sections )
refs = [ ]
for ind , sec in sections :
    if maxdepth and ind - outer + 1 > maxdepth :
        continue
    ref = sec . lower ( )
    ref = ref . replace ( '`' , '' )
    ref = ref . replace ( ' ' , '-' )
    ref = ref . replace ( '?' , '' )
    refs . append ( "    " * ( ind - outer ) + "- [%s](#%s)" % ( sec , ref ) )
return refs


signature:
def doc2md ( docstr , title , min_level = 1 , more_info = False , toc = True , maxdepth = 0 ) :
    """Convert a docstring to a markdown text ."""

implementation:
text = doctrim ( docstr )
lines = text . split ( '\n' )
sections = find_sections ( lines )
if sections :
    level = min ( n for n , t in sections ) - 1
else :
    level = 1
shiftlevel = 0
if level < min_level :
    shiftlevel = min_level - level
    level = min_level
    sections = [ ( lev + shiftlevel , tit ) for lev , tit in sections ]
head = next ( ( i for i , l in enumerate ( lines ) if is_heading ( l ) ) , 0 )
md = [ make_heading ( level , title ) , "" , ] + lines [ : head ]
if toc :
    md += make_toc ( sections , maxdepth )
    md += [ '' ]
md += _doc2md ( lines [ head : ] , shiftlevel )
if more_info :
    return ( md , sections )
else :
    return "\n" . join ( md )


signature:
def mod2md ( module , title , title_api_section , toc = True , maxdepth = 0 ) :
    """Generate markdown document from module , including API section ."""

implementation:
docstr = module . __doc__
text = doctrim ( docstr )
lines = text . split ( '\n' )
sections = find_sections ( lines )
if sections :
    level = min ( n for n , t in sections ) - 1
else :
    level = 1
api_md = [ ]
api_sec = [ ]
if title_api_section and module . __all__ :
    sections . append ( ( level + 1 , title_api_section ) )
    for name in module . __all__ :
        api_sec . append ( ( level + 2 , "`" + name + "`" ) )
        api_md += [ '' , '' ]
        entry = module . __dict__ [ name ]
        if entry . __doc__ :
            md , sec = doc2md ( entry . __doc__ , "`" + name + "`" , min_level = level + 2 , more_info = True , toc = False )
            api_sec += sec
            api_md += md
sections += api_sec
# headline
head = next ( ( i for i , l in enumerate ( lines ) if is_heading ( l ) ) , 0 )
md = [ make_heading ( level , title ) , "" , ] + lines [ : head ]
# main sections
if toc :
    md += make_toc ( sections , maxdepth )
    md += [ '' ]
md += _doc2md ( lines [ head : ] )
# API section
md += [ '' , '' , make_heading ( level + 1 , title_api_section ) , ]
if toc :
    md += [ '' ]
    md += make_toc ( api_sec , 1 )
md += api_md
return "\n" . join ( md )


signature:
def largest_finite_distance ( self ) :
    """Compute the maximum temporal distance .
 Returns
 max _ temporal _ distance : float"""

implementation:
block_start_distances = [ block . distance_start for block in self . _profile_blocks if block . distance_start < float ( 'inf' ) ]
block_end_distances = [ block . distance_end for block in self . _profile_blocks if block . distance_end < float ( 'inf' ) ]
distances = block_start_distances + block_end_distances
if len ( distances ) > 0 :
    return max ( distances )
else :
    return None


signature:
def _temporal_distance_cdf ( self ) :
    """Temporal distance cumulative density function .
 Returns
 x _ values : numpy . array
 values for the x - axis
 cdf : numpy . array
 cdf values"""

implementation:
distance_split_points = set ( )
for block in self . _profile_blocks :
    if block . distance_start != float ( 'inf' ) :
        distance_split_points . add ( block . distance_end )
        distance_split_points . add ( block . distance_start )
distance_split_points_ordered = numpy . array ( sorted ( list ( distance_split_points ) ) )
temporal_distance_split_widths = distance_split_points_ordered [ 1 : ] - distance_split_points_ordered [ : - 1 ]
trip_counts = numpy . zeros ( len ( temporal_distance_split_widths ) )
delta_peaks = defaultdict ( lambda : 0 )
for block in self . _profile_blocks :
    if block . distance_start == block . distance_end :
        delta_peaks [ block . distance_end ] += block . width ( )
    else :
        start_index = numpy . searchsorted ( distance_split_points_ordered , block . distance_end )
        end_index = numpy . searchsorted ( distance_split_points_ordered , block . distance_start )
        trip_counts [ start_index : end_index ] += 1
unnormalized_cdf = numpy . array ( [ 0 ] + list ( numpy . cumsum ( temporal_distance_split_widths * trip_counts ) ) )
if not ( numpy . isclose ( [ unnormalized_cdf [ - 1 ] ] , [ self . _end_time - self . _start_time - sum ( delta_peaks . values ( ) ) ] , atol = 1E-4 ) . all ( ) ) :
    print ( unnormalized_cdf [ - 1 ] , self . _end_time - self . _start_time - sum ( delta_peaks . values ( ) ) )
    raise RuntimeError ( "Something went wrong with cdf computation!" )
if len ( delta_peaks ) > 0 :
    for peak in delta_peaks . keys ( ) :
        if peak == float ( 'inf' ) :
            continue
        index = numpy . nonzero ( distance_split_points_ordered == peak ) [ 0 ] [ 0 ]
        unnormalized_cdf = numpy . insert ( unnormalized_cdf , index , unnormalized_cdf [ index ] )
        distance_split_points_ordered = numpy . insert ( distance_split_points_ordered , index , distance_split_points_ordered [ index ] )
        # walk _ waiting _ time _ fraction = walk _ total _ time / ( self . end _ time _ dep - self . start _ time _ dep )
        unnormalized_cdf [ ( index + 1 ) : ] = unnormalized_cdf [ ( index + 1 ) : ] + delta_peaks [ peak ]
norm_cdf = unnormalized_cdf / ( unnormalized_cdf [ - 1 ] + delta_peaks [ float ( 'inf' ) ] )
return distance_split_points_ordered , norm_cdf


signature:
def _temporal_distance_pdf ( self ) :
    """Temporal distance probability density function .
 Returns
 non _ delta _ peak _ split _ points : numpy . array
 non _ delta _ peak _ densities : numpy . array
 len ( density ) = = len ( temporal _ distance _ split _ points _ ordered ) - 1
 delta _ peak _ loc _ to _ probability _ mass : dict"""

implementation:
temporal_distance_split_points_ordered , norm_cdf = self . _temporal_distance_cdf ( )
delta_peak_loc_to_probability_mass = { }
non_delta_peak_split_points = [ temporal_distance_split_points_ordered [ 0 ] ]
non_delta_peak_densities = [ ]
for i in range ( 0 , len ( temporal_distance_split_points_ordered ) - 1 ) :
    left = temporal_distance_split_points_ordered [ i ]
    right = temporal_distance_split_points_ordered [ i + 1 ]
    width = right - left
    prob_mass = norm_cdf [ i + 1 ] - norm_cdf [ i ]
    if width == 0.0 :
        delta_peak_loc_to_probability_mass [ left ] = prob_mass
    else :
        non_delta_peak_split_points . append ( right )
        non_delta_peak_densities . append ( prob_mass / float ( width ) )
assert ( len ( non_delta_peak_densities ) == len ( non_delta_peak_split_points ) - 1 )
return numpy . array ( non_delta_peak_split_points ) , numpy . array ( non_delta_peak_densities ) , delta_peak_loc_to_probability_mass


signature:
def remove_all_trips_fully_outside_buffer ( db_conn , center_lat , center_lon , buffer_km , update_secondary_data = True ) :
    """Not used in the regular filter process for the time being .
 Parameters
 db _ conn : sqlite3 . Connection
 connection to the GTFS object
 center _ lat : float
 center _ lon : float
 buffer _ km : float"""

implementation:
distance_function_str = add_wgs84_distance_function_to_db ( db_conn )
stops_within_buffer_query_sql = "SELECT stop_I FROM stops WHERE CAST(" + distance_function_str + "(lat, lon, {lat} , {lon}) AS INT) < {d_m}" . format ( lat = float ( center_lat ) , lon = float ( center_lon ) , d_m = int ( 1000 * buffer_km ) )
select_all_trip_Is_where_stop_I_is_within_buffer_sql = "SELECT distinct(trip_I) FROM stop_times WHERE stop_I IN (" + stops_within_buffer_query_sql + ")"
trip_Is_to_remove_sql = "SELECT trip_I FROM trips WHERE trip_I NOT IN ( " + select_all_trip_Is_where_stop_I_is_within_buffer_sql + ")"
trip_Is_to_remove = pandas . read_sql ( trip_Is_to_remove_sql , db_conn ) [ "trip_I" ] . values
trip_Is_to_remove_string = "," . join ( [ str ( trip_I ) for trip_I in trip_Is_to_remove ] )
remove_all_trips_fully_outside_buffer_sql = "DELETE FROM trips WHERE trip_I IN (" + trip_Is_to_remove_string + ")"
remove_all_stop_times_where_trip_I_fully_outside_buffer_sql = "DELETE FROM stop_times WHERE trip_I IN (" + trip_Is_to_remove_string + ")"
db_conn . execute ( remove_all_trips_fully_outside_buffer_sql )
db_conn . execute ( remove_all_stop_times_where_trip_I_fully_outside_buffer_sql )
delete_stops_not_in_stop_times_and_not_as_parent_stop ( db_conn )
db_conn . execute ( DELETE_ROUTES_NOT_PRESENT_IN_TRIPS_SQL )
db_conn . execute ( DELETE_SHAPES_NOT_REFERENCED_IN_TRIPS_SQL )
db_conn . execute ( DELETE_DAYS_ENTRIES_NOT_PRESENT_IN_TRIPS_SQL )
db_conn . execute ( DELETE_DAY_TRIPS2_ENTRIES_NOT_PRESENT_IN_TRIPS_SQL )
db_conn . execute ( DELETE_CALENDAR_ENTRIES_FOR_NON_REFERENCE_SERVICE_IS_SQL )
db_conn . execute ( DELETE_CALENDAR_DATES_ENTRIES_FOR_NON_REFERENCE_SERVICE_IS_SQL )
db_conn . execute ( DELETE_FREQUENCIES_ENTRIES_NOT_PRESENT_IN_TRIPS )
db_conn . execute ( DELETE_AGENCIES_NOT_REFERENCED_IN_ROUTES_SQL )
if update_secondary_data :
    update_secondary_data_copies ( db_conn )


signature:
def remove_dangling_shapes ( db_conn ) :
    """Remove dangling entries from the shapes directory .
 Parameters
 db _ conn : sqlite3 . Connection
 connection to the GTFS object"""

implementation:
db_conn . execute ( DELETE_SHAPES_NOT_REFERENCED_IN_TRIPS_SQL )
SELECT_MIN_MAX_SHAPE_BREAKS_BY_TRIP_I_SQL = "SELECT trips.trip_I, shape_id, min(shape_break) as min_shape_break, max(shape_break) as max_shape_break FROM trips, stop_times WHERE trips.trip_I=stop_times.trip_I GROUP BY trips.trip_I"
trip_min_max_shape_seqs = pandas . read_sql ( SELECT_MIN_MAX_SHAPE_BREAKS_BY_TRIP_I_SQL , db_conn )
rows = [ ]
for row in trip_min_max_shape_seqs . itertuples ( ) :
    shape_id , min_shape_break , max_shape_break = row . shape_id , row . min_shape_break , row . max_shape_break
    if min_shape_break is None or max_shape_break is None :
        min_shape_break = float ( '-inf' )
        max_shape_break = float ( '-inf' )
    rows . append ( ( shape_id , min_shape_break , max_shape_break ) )
DELETE_SQL_BASE = "DELETE FROM shapes WHERE shape_id=? AND (seq<? OR seq>?)"
db_conn . executemany ( DELETE_SQL_BASE , rows )
remove_dangling_shapes_references ( db_conn )


signature:
def _delete_rows_by_start_and_end_date ( self ) :
    """Removes rows from the sqlite database copy that are out of the time span defined by start _ date and end _ date
 : param gtfs : GTFS object
 : param copy _ db _ conn : sqlite database connection
 : param start _ date :
 : param end _ date :
 : return :"""

implementation:
# filter by start _ time _ ut and end _ date _ ut :
if ( self . start_date is not None ) and ( self . end_date is not None ) :
    start_date_ut = self . gtfs . get_day_start_ut ( self . start_date )
    end_date_ut = self . gtfs . get_day_start_ut ( self . end_date )
    if self . copy_db_conn . execute ( "SELECT count(*) FROM day_trips2 WHERE start_time_ut IS null " "OR end_time_ut IS null" ) . fetchone ( ) != ( 0 , ) :
        raise ValueError ( "Missing information in day_trips2 (start_time_ut and/or end_time_ut), " "check trips.start_time_ds and trips.end_time_ds." )
    logging . info ( "Filtering based on start_time_ut and end_time_ut" )
    table_to_preserve_map = { "calendar" : "start_date < date({filter_end_ut}, 'unixepoch', 'localtime') " "AND " "end_date >= date({filter_start_ut}, 'unixepoch', 'localtime') " , "calendar_dates" : "date >= date({filter_start_ut}, 'unixepoch', 'localtime') " "AND " "date < date({filter_end_ut}, 'unixepoch', 'localtime') " , "day_trips2" : 'start_time_ut < {filter_end_ut} ' 'AND ' 'end_time_ut > {filter_start_ut} ' , "days" : "day_start_ut >= {filter_start_ut} " "AND " "day_start_ut < {filter_end_ut} " }
    table_to_remove_map = { key : "WHERE NOT ( " + to_preserve + " );" for key , to_preserve in table_to_preserve_map . items ( ) }
    # Ensure that process timezone is correct as we rely on ' localtime ' in the SQL statements .
    GTFS ( self . copy_db_conn ) . set_current_process_time_zone ( )
    # remove the ' source ' entries from tables
    for table , query_template in table_to_remove_map . items ( ) :
        param_dict = { "filter_start_ut" : str ( start_date_ut ) , "filter_end_ut" : str ( end_date_ut ) }
        query = "DELETE FROM " + table + " " + query_template . format ( ** param_dict )
        self . copy_db_conn . execute ( query )
        self . copy_db_conn . commit ( )
    return FILTERED
else :
    return NOT_FILTERED


signature:
def _filter_by_calendar ( self ) :
    """update calendar table ' s services
 : param copy _ db _ conn :
 : param start _ date :
 : param end _ date :
 : return :"""

implementation:
if ( self . start_date is not None ) and ( self . end_date is not None ) :
    logging . info ( "Making date extract" )
    start_date_query = "UPDATE calendar " "SET start_date='{start_date}' " "WHERE start_date<'{start_date}' " . format ( start_date = self . start_date )
    self . copy_db_conn . execute ( start_date_query )
    end_date_query = "UPDATE calendar " "SET end_date='{end_date_to_include}' " "WHERE end_date>'{end_date_to_include}' " . format ( end_date_to_include = self . end_date_to_include_str )
    self . copy_db_conn . execute ( end_date_query )
    # then recursively delete further data :
    self . copy_db_conn . execute ( DELETE_TRIPS_NOT_IN_DAYS_SQL )
    self . copy_db_conn . execute ( DELETE_SHAPES_NOT_REFERENCED_IN_TRIPS_SQL )
    self . copy_db_conn . execute ( DELETE_STOP_TIMES_NOT_REFERENCED_IN_TRIPS_SQL )
    delete_stops_not_in_stop_times_and_not_as_parent_stop ( self . copy_db_conn )
    self . copy_db_conn . execute ( DELETE_STOP_DISTANCE_ENTRIES_WITH_NONEXISTENT_STOPS_SQL )
    self . copy_db_conn . execute ( DELETE_ROUTES_NOT_PRESENT_IN_TRIPS_SQL )
    self . copy_db_conn . execute ( DELETE_AGENCIES_NOT_REFERENCED_IN_ROUTES_SQL )
    self . copy_db_conn . commit ( )
    return FILTERED
else :
    return NOT_FILTERED


signature:
def _filter_by_agency ( self ) :
    """filter by agency ids
 : param copy _ db _ conn :
 : param agency _ ids _ to _ preserve :
 : return :"""

implementation:
if self . agency_ids_to_preserve is not None :
    logging . info ( "Filtering based on agency_ids" )
    agency_ids_to_preserve = list ( self . agency_ids_to_preserve )
    agencies = pandas . read_sql ( "SELECT * FROM agencies" , self . copy_db_conn )
    agencies_to_remove = [ ]
    for idx , row in agencies . iterrows ( ) :
        if row [ 'agency_id' ] not in agency_ids_to_preserve :
            agencies_to_remove . append ( row [ 'agency_id' ] )
    for agency_id in agencies_to_remove :
        self . copy_db_conn . execute ( 'DELETE FROM agencies WHERE agency_id=?' , ( agency_id , ) )
    # and remove recursively related to the agencies :
    self . copy_db_conn . execute ( 'DELETE FROM routes WHERE ' 'agency_I NOT IN (SELECT agency_I FROM agencies)' )
    self . copy_db_conn . execute ( 'DELETE FROM trips WHERE ' 'route_I NOT IN (SELECT route_I FROM routes)' )
    self . copy_db_conn . execute ( 'DELETE FROM calendar WHERE ' 'service_I NOT IN (SELECT service_I FROM trips)' )
    self . copy_db_conn . execute ( 'DELETE FROM calendar_dates WHERE ' 'service_I NOT IN (SELECT service_I FROM trips)' )
    self . copy_db_conn . execute ( 'DELETE FROM days WHERE ' 'trip_I NOT IN (SELECT trip_I FROM trips)' )
    self . copy_db_conn . execute ( 'DELETE FROM stop_times WHERE ' 'trip_I NOT IN (SELECT trip_I FROM trips)' )
    self . copy_db_conn . execute ( 'DELETE FROM stop_times WHERE ' 'trip_I NOT IN (SELECT trip_I FROM trips)' )
    self . copy_db_conn . execute ( 'DELETE FROM shapes WHERE ' 'shape_id NOT IN (SELECT shape_id FROM trips)' )
    self . copy_db_conn . execute ( 'DELETE FROM day_trips2 WHERE ' 'trip_I NOT IN (SELECT trip_I FROM trips)' )
    self . copy_db_conn . commit ( )
    return FILTERED
else :
    return NOT_FILTERED


signature:
def _filter_spatially ( self ) :
    """Filter the feed based on self . buffer _ distance _ km from self . buffer _ lon and self . buffer _ lat .
 1 . First include all stops that are within self . buffer _ distance _ km from self . buffer _ lon and self . buffer _ lat .
 2 . Then include all intermediate stops that are between any of the included stop pairs with some PT trip .
 3 . Repeat step 2 until no more stops are to be included .
 As a summary this process should get rid of PT network tendrils , but should preserve the PT network intact
 at its core ."""

implementation:
if self . buffer_lat is None or self . buffer_lon is None or self . buffer_distance_km is None :
    return NOT_FILTERED
print ( "filtering with lat: " + str ( self . buffer_lat ) + " lon: " + str ( self . buffer_lon ) + " buffer distance: " + str ( self . buffer_distance_km ) )
remove_all_trips_fully_outside_buffer ( self . copy_db_conn , self . buffer_lat , self . buffer_lon , self . buffer_distance_km , update_secondary_data = False )
logging . info ( "Making spatial extract" )
find_distance_func_name = add_wgs84_distance_function_to_db ( self . copy_db_conn )
assert find_distance_func_name == "find_distance"
# select all stops that are within the buffer and have some stop _ times assigned .
stop_distance_filter_sql_base = ( "SELECT DISTINCT stops.stop_I FROM stops, stop_times" + "    WHERE CAST(find_distance(lat, lon, {buffer_lat}, {buffer_lon}) AS INT) < {buffer_distance_meters}" + "     AND stops.stop_I=stop_times.stop_I" )
stops_within_buffer_sql = stop_distance_filter_sql_base . format ( buffer_lat = float ( self . buffer_lat ) , buffer_lon = float ( self . buffer_lon ) , buffer_distance_meters = int ( self . buffer_distance_km * 1000 ) )
stops_within_buffer = set ( row [ 0 ] for row in self . copy_db_conn . execute ( stops_within_buffer_sql ) )
# For each trip _ I , find smallest ( min _ seq ) and largest ( max _ seq ) stop sequence numbers that
# are within the soft buffer _ distance from the buffer _ lon and buffer _ lat , and add them into the
# list of stops to preserve .
# Note that if a trip is OUT - IN - OUT - IN - OUT , this process preserves ( at least ) the part IN - OUT - IN of the trip .
# Repeat until no more stops are found .
stops_within_buffer_string = "(" + "," . join ( str ( stop_I ) for stop_I in stops_within_buffer ) + ")"
trip_min_max_include_seq_sql = ( 'SELECT trip_I, min(seq) AS min_seq, max(seq) AS max_seq FROM stop_times, stops ' 'WHERE stop_times.stop_I = stops.stop_I ' ' AND stops.stop_I IN {stop_I_list}' ' GROUP BY trip_I' ) . format ( stop_I_list = stops_within_buffer_string )
trip_I_min_seq_max_seq_df = pandas . read_sql ( trip_min_max_include_seq_sql , self . copy_db_conn )
for trip_I_seq_row in trip_I_min_seq_max_seq_df . itertuples ( ) :
    trip_I = trip_I_seq_row . trip_I
    min_seq = trip_I_seq_row . min_seq
    max_seq = trip_I_seq_row . max_seq
    # DELETE FROM STOP _ TIMES
    if min_seq == max_seq : # Only one entry in stop _ times to be left , remove whole trip .
        self . copy_db_conn . execute ( "DELETE FROM stop_times WHERE trip_I={trip_I}" . format ( trip_I = trip_I ) )
        self . copy_db_conn . execute ( "DELETE FROM trips WHERE trip_i={trip_I}" . format ( trip_I = trip_I ) )
    else : # DELETE STOP _ TIME ENTRIES BEFORE ENTERING AND AFTER DEPARTING THE BUFFER AREA
        DELETE_STOP_TIME_ENTRIES_SQL = "DELETE FROM stop_times WHERE trip_I={trip_I} AND (seq<{min_seq} OR seq>{max_seq})" . format ( trip_I = trip_I , max_seq = max_seq , min_seq = min_seq )
        self . copy_db_conn . execute ( DELETE_STOP_TIME_ENTRIES_SQL )
        STOPS_NOT_WITHIN_BUFFER__FOR_TRIP_SQL = "SELECT seq, stop_I IN {stops_within_hard_buffer} AS within FROM stop_times WHERE trip_I={trip_I} ORDER BY seq" . format ( stops_within_hard_buffer = stops_within_buffer_string , trip_I = trip_I )
        stop_times_within_buffer_df = pandas . read_sql ( STOPS_NOT_WITHIN_BUFFER__FOR_TRIP_SQL , self . copy_db_conn )
        if stop_times_within_buffer_df [ 'within' ] . all ( ) :
            continue
        else :
            _split_trip ( self . copy_db_conn , trip_I , stop_times_within_buffer_df )
# Delete all shapes that are not fully within the buffer to avoid shapes going outside
# the buffer area in a some cases .
# This could probably be done in some more sophisticated way though ( per trip )
SHAPE_IDS_NOT_WITHIN_BUFFER_SQL = "SELECT DISTINCT shape_id FROM SHAPES " "WHERE CAST(find_distance(lat, lon, {buffer_lat}, {buffer_lon}) AS INT) > {buffer_distance_meters}" . format ( buffer_lat = self . buffer_lat , buffer_lon = self . buffer_lon , buffer_distance_meters = self . buffer_distance_km * 1000 )
DELETE_ALL_SHAPE_IDS_NOT_WITHIN_BUFFER_SQL = "DELETE FROM shapes WHERE shape_id IN (" + SHAPE_IDS_NOT_WITHIN_BUFFER_SQL + ")"
self . copy_db_conn . execute ( DELETE_ALL_SHAPE_IDS_NOT_WITHIN_BUFFER_SQL )
SET_SHAPE_ID_TO_NULL_FOR_HARD_BUFFER_FILTERED_SHAPE_IDS = "UPDATE trips SET shape_id=NULL WHERE trips.shape_id IN (" + SHAPE_IDS_NOT_WITHIN_BUFFER_SQL + ")"
self . copy_db_conn . execute ( SET_SHAPE_ID_TO_NULL_FOR_HARD_BUFFER_FILTERED_SHAPE_IDS )
# Delete trips with only one stop
self . copy_db_conn . execute ( 'DELETE FROM stop_times WHERE ' 'trip_I IN (SELECT trip_I FROM ' '(SELECT trip_I, count(*) AS N_stops from stop_times ' 'GROUP BY trip_I) q1 ' 'WHERE N_stops = 1)' )
# Delete trips with only one stop but several instances in stop _ times
self . copy_db_conn . execute ( 'DELETE FROM stop_times WHERE ' 'trip_I IN (SELECT q1.trip_I AS trip_I FROM ' '(SELECT trip_I, stop_I, count(*) AS stops_per_stop FROM stop_times ' 'GROUP BY trip_I, stop_I) q1, ' '(SELECT trip_I, count(*) as n_stops FROM stop_times ' 'GROUP BY trip_I) q2 ' 'WHERE q1.trip_I = q2.trip_I AND n_stops = stops_per_stop)' )
# Delete all stop _ times for uncovered stops
delete_stops_not_in_stop_times_and_not_as_parent_stop ( self . copy_db_conn )
# Consecutively delete all the rest remaining .
self . copy_db_conn . execute ( DELETE_TRIPS_NOT_REFERENCED_IN_STOP_TIMES )
self . copy_db_conn . execute ( DELETE_ROUTES_NOT_PRESENT_IN_TRIPS_SQL )
self . copy_db_conn . execute ( DELETE_AGENCIES_NOT_REFERENCED_IN_ROUTES_SQL )
self . copy_db_conn . execute ( DELETE_SHAPES_NOT_REFERENCED_IN_TRIPS_SQL )
self . copy_db_conn . execute ( DELETE_STOP_DISTANCE_ENTRIES_WITH_NONEXISTENT_STOPS_SQL )
self . copy_db_conn . execute ( DELETE_FREQUENCIES_ENTRIES_NOT_PRESENT_IN_TRIPS )
remove_dangling_shapes ( self . copy_db_conn )
self . copy_db_conn . commit ( )
return FILTERED


signature:
def compute_pseudo_connections ( transit_connections , start_time_dep , end_time_dep , transfer_margin , walk_network , walk_speed ) :
    """Given a set of transit events and the static walk network ,
 " transform " the static walking network into a set of " pseudo - connections " .
 As a first approximation , we add pseudo - connections to depart after each arrival of a transit connection
 to it ' s arrival stop .
 Parameters
 transit _ connections : list [ Connection ]
 start _ time _ dep : int
 start time in unixtime seconds
 end _ time _ dep : int
 end time in unixtime seconds ( no new connections will be scanned after this time )
 transfer _ margin : int
 required extra margin required for transfers in seconds
 walk _ speed : float
 walking speed between stops in meters / second
 walk _ network : networkx . Graph
 each edge should have the walking distance as a data attribute ( " d _ walk " ) expressed in meters
 Returns
 pseudo _ connections : set [ Connection ]"""

implementation:
# A pseudo - connection should be created after ( each ) arrival to a transit _ connection ' s arrival stop .
pseudo_connection_set = set ( )
# use a set to ignore possible duplicates
for c in transit_connections :
    if start_time_dep <= c . departure_time <= end_time_dep :
        walk_arr_stop = c . departure_stop
        walk_arr_time = c . departure_time - transfer_margin
        for _ , walk_dep_stop , data in walk_network . edges ( nbunch = [ walk_arr_stop ] , data = True ) :
            walk_dep_time = walk_arr_time - data [ 'd_walk' ] / float ( walk_speed )
            if walk_dep_time > end_time_dep or walk_dep_time < start_time_dep :
                continue
            pseudo_connection = Connection ( walk_dep_stop , walk_arr_stop , walk_dep_time , walk_arr_time , Connection . WALK_TRIP_ID , Connection . WALK_SEQ , is_walk = True )
            pseudo_connection_set . add ( pseudo_connection )
return pseudo_connection_set


signature:
def get_min_visit_time ( self ) :
    """Get the earliest visit time of the stop ."""

implementation:
if not self . visit_events :
    return float ( 'inf' )
else :
    return min ( self . visit_events , key = lambda event : event . arr_time_ut ) . arr_time_ut


signature:
def visit ( self , event ) :
    """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"""

implementation:
to_visit = False
if event . arr_time_ut <= self . min_transfer_time + self . get_min_visit_time ( ) :
    to_visit = True
else :
    for ve in self . visit_events :
        if ( event . trip_I == ve . trip_I ) and event . arr_time_ut < ve . arr_time_ut :
            to_visit = True
if to_visit :
    self . visit_events . append ( event )
    min_time = self . get_min_visit_time ( )
    # remove any visits that are ' too old '
    self . visit_events = [ v for v in self . visit_events if v . arr_time_ut <= min_time + self . min_transfer_time ]
return to_visit


signature:
def can_infect ( self , event ) :
    """Whether the spreading stop can infect using this event ."""

implementation:
if event . from_stop_I != self . stop_I :
    return False
if not self . has_been_visited ( ) :
    return False
else :
    time_sep = event . dep_time_ut - self . get_min_visit_time ( )
    # if the gap between the earliest visit _ time and current time is
    # smaller than the min . transfer time , the stop can pass the spreading
    # forward
    if ( time_sep >= self . min_transfer_time ) or ( event . trip_I == - 1 and time_sep >= 0 ) :
        return True
    else :
        for visit in self . visit_events : # if no transfer , please hop - on
            if ( event . trip_I == visit . trip_I ) and ( time_sep >= 0 ) :
                return True
    return False


signature:
def get_transit_connections ( gtfs , start_time_ut , end_time_ut ) :
    """Parameters
 gtfs : gtfspy . GTFS
 end _ time _ ut : int
 start _ time _ ut : int
 Returns
 list [ Connection ]"""

implementation:
if start_time_ut + 20 * 3600 < end_time_ut :
    warn ( "Note that it is possible that same trip_I's can take place during multiple days, " "which could (potentially) affect the outcomes of the CSA routing!" )
assert ( isinstance ( gtfs , GTFS ) )
events_df = temporal_network ( gtfs , start_time_ut = start_time_ut , end_time_ut = end_time_ut )
assert ( isinstance ( events_df , pandas . DataFrame ) )
return list ( map ( lambda e : Connection ( e . from_stop_I , e . to_stop_I , e . dep_time_ut , e . arr_time_ut , e . trip_I , e . seq ) , events_df . itertuples ( ) ) )


signature:
def get_walk_network ( gtfs , max_link_distance_m = 1000 ) :
    """Parameters
 gtfs : gtfspy . GTFS
 Returns
 walk _ network : networkx . Graph :"""

implementation:
assert ( isinstance ( gtfs , GTFS ) )
return walk_transfer_stop_to_stop_network ( gtfs , max_link_distance = max_link_distance_m )


signature:
def calculate_trip_shape_breakpoints ( conn ) :
    """Pre - compute the shape points corresponding to each trip ' s stop .
 Depends : shapes"""

implementation:
from gtfspy import shapes
cur = conn . cursor ( )
breakpoints_cache = { }
# Counters for problems - don ' t print every problem .
count_bad_shape_ordering = 0
count_bad_shape_fit = 0
count_no_shape_fit = 0
trip_Is = [ x [ 0 ] for x in cur . execute ( 'SELECT DISTINCT trip_I FROM stop_times' ) . fetchall ( ) ]
for trip_I in trip_Is : # Get the shape points
    row = cur . execute ( '''SELECT shape_id
                                  FROM trips WHERE trip_I=?''' , ( trip_I , ) ) . fetchone ( )
    if row is None :
        continue
    shape_id = row [ 0 ]
    if shape_id is None or shape_id == '' :
        continue
    # Get the stop points
    cur . execute ( '''SELECT seq, lat, lon, stop_id
                       FROM stop_times LEFT JOIN stops USING (stop_I)
                       WHERE trip_I=?
                       ORDER BY seq''' , ( trip_I , ) )
    # print ' % 20s , % s ' % ( run _ code , datetime . fromtimestamp ( run _ sch _ starttime ) )
    stop_points = [ dict ( seq = row [ 0 ] , lat = row [ 1 ] , lon = row [ 2 ] , stop_I = row [ 3 ] ) for row in cur if row [ 1 ] and row [ 2 ] ]
    # Calculate a cache key for this sequence .
    # If both shape _ id , and all stop _ Is are same , then we can re - use existing breakpoints :
    cache_key = ( shape_id , tuple ( x [ 'stop_I' ] for x in stop_points ) )
    if cache_key in breakpoints_cache :
        breakpoints = breakpoints_cache [ cache_key ]
    else : # Must re - calculate breakpoints :
        shape_points = shapes . get_shape_points ( cur , shape_id )
        breakpoints , badness = shapes . find_segments ( stop_points , shape_points )
        if breakpoints != sorted ( breakpoints ) : # route _ name , route _ id , route _ I , trip _ id , trip _ I = \
        # cur . execute ( ' ' ' SELECT name , route _ id , route _ I , trip _ id , trip _ I
        # FROM trips LEFT JOIN routes USING ( route _ I )
        # WHERE trip _ I = ? LIMIT 1 ' ' ' , ( trip _ I , ) ) . fetchone ( )
        # print " Ignoring : Route with bad shape ordering : " , route _ name , route _ id , route _ I , trip _ id , trip _ I
            count_bad_shape_ordering += 1
            # select * from stop _ times where trip _ I = NNNN order by shape _ break ;
            breakpoints_cache [ cache_key ] = None
            continue
            # Do not set shape _ break for this trip .
        # Add it to cache
        breakpoints_cache [ cache_key ] = breakpoints
        if badness > 30 * len ( breakpoints ) : # print " bad shape fit : % s ( % s , % s , % s ) " % ( badness , trip _ I , shape _ id , len ( breakpoints ) )
            count_bad_shape_fit += 1
    if breakpoints is None :
        continue
    if len ( breakpoints ) == 0 : # No valid route could be identified .
    # print " Ignoring : No shape identified for trip _ I = % s , shape _ id = % s " % ( trip _ I , shape _ id )
        count_no_shape_fit += 1
        continue
    # breakpoints is the corresponding points for each stop
    assert len ( breakpoints ) == len ( stop_points )
    cur . executemany ( 'UPDATE stop_times SET shape_break=? ' 'WHERE trip_I=? AND seq=? ' , ( ( int ( bkpt ) , int ( trip_I ) , int ( stpt [ 'seq' ] ) ) for bkpt , stpt in zip ( breakpoints , stop_points ) ) )
if count_bad_shape_fit > 0 :
    print ( " Shape trip breakpoints: %s bad fits" % count_bad_shape_fit )
if count_bad_shape_ordering > 0 :
    print ( " Shape trip breakpoints: %s bad shape orderings" % count_bad_shape_ordering )
if count_no_shape_fit > 0 :
    print ( " Shape trip breakpoints: %s no shape fits" % count_no_shape_fit )
conn . commit ( )


signature:
def import_journey_data_for_target_stop ( self , target_stop_I , origin_stop_I_to_journey_labels , enforce_synchronous_writes = False ) :
    """Parameters
 origin _ stop _ I _ to _ journey _ labels : dict
 key : origin _ stop _ Is
 value : list of labels
 target _ stop _ I : int"""

implementation:
cur = self . conn . cursor ( )
self . conn . isolation_level = 'EXCLUSIVE'
# if not enforce _ synchronous _ writes :
cur . execute ( 'PRAGMA synchronous = 0;' )
if self . track_route :
    self . _insert_journeys_with_route_into_db ( origin_stop_I_to_journey_labels , target_stop = int ( target_stop_I ) )
else :
    self . _insert_journeys_into_db_no_route ( origin_stop_I_to_journey_labels , target_stop = int ( target_stop_I ) )
print ( "Finished import process" )
self . conn . commit ( )


signature:
def _insert_journeys_into_db_no_route ( self , stop_profiles , target_stop = None ) : # TODO : Change the insertion so that the check last journey id and insertions are in the same transaction block
    """con . isolation _ level = ' EXCLUSIVE '
 con . execute ( ' BEGIN EXCLUSIVE ' )
 # exclusive access starts here . Nothing else can r / w the db , do your magic here .
 con . commit ( )"""

implementation:
print ( "Collecting journey data" )
journey_id = 1
journey_list = [ ]
tot = len ( stop_profiles )
for i , ( origin_stop , labels ) in enumerate ( stop_profiles . items ( ) , start = 1 ) : # print ( " \ r Stop " + str ( i ) + " of " + str ( tot ) , end = ' ' , flush = True )
    for label in labels :
        assert ( isinstance ( label , LabelTimeWithBoardingsCount ) )
        if self . multitarget_routing :
            target_stop = None
        else :
            target_stop = int ( target_stop )
        values = [ int ( journey_id ) , int ( origin_stop ) , target_stop , int ( label . departure_time ) , int ( label . arrival_time_target ) , int ( label . n_boardings ) ]
        journey_list . append ( values )
        journey_id += 1
print ( "Inserting journeys without route into database" )
insert_journeys_stmt = '''INSERT INTO journeys(
              journey_id,
              from_stop_I,
              to_stop_I,
              departure_time,
              arrival_time_target,
              n_boardings) VALUES (%s) ''' % ( ", " . join ( [ "?" for x in range ( 6 ) ] ) )
# self . conn . executemany ( insert _ journeys _ stmt , journey _ list )
self . _executemany_exclusive ( insert_journeys_stmt , journey_list )
self . conn . commit ( )


signature:
def _journey_label_generator ( self , destination_stop_Is = None , origin_stop_Is = None ) :
    """Parameters
 destination _ stop _ Is : list - like
 origin _ stop _ Is : list - like
 Yields
 ( origin _ stop _ I , destination _ stop _ I , journey _ labels ) : tuple"""

implementation:
conn = self . conn
conn . row_factory = sqlite3 . Row
if destination_stop_Is is None :
    destination_stop_Is = self . get_targets_having_journeys ( )
if origin_stop_Is is None :
    origin_stop_Is = self . get_origins_having_journeys ( )
for destination_stop_I in destination_stop_Is :
    if self . track_route :
        label_features = "journey_id, from_stop_I, to_stop_I, n_boardings, movement_duration, " "journey_duration, in_vehicle_duration, transfer_wait_duration, walking_duration, " "departure_time, arrival_time_target" ""
    else :
        label_features = "journey_id, from_stop_I, to_stop_I, n_boardings, departure_time, " "arrival_time_target"
    sql = "SELECT " + label_features + " FROM journeys WHERE to_stop_I = %s" % destination_stop_I
    df = pd . read_sql_query ( sql , self . conn )
    for origin_stop_I in origin_stop_Is :
        selection = df . loc [ df [ 'from_stop_I' ] == origin_stop_I ]
        journey_labels = [ ]
        for journey in selection . to_dict ( orient = 'records' ) :
            journey [ "pre_journey_wait_fp" ] = - 1
            try :
                journey_labels . append ( LabelGeneric ( journey ) )
            except Exception as e :
                print ( journey )
                raise e
        yield origin_stop_I , destination_stop_I , journey_labels


signature:
def _insert_travel_impedance_data_to_db ( self , travel_impedance_measure_name , data ) :
    """Parameters
 travel _ impedance _ measure _ name : str
 data : list [ dict ]
 Each list element must contain keys :
 " from _ stop _ I " , " to _ stop _ I " , " min " , " max " , " median " and " mean " """

implementation:
f = float
data_tuple = [ ( x [ "from_stop_I" ] , x [ "to_stop_I" ] , f ( x [ "min" ] ) , f ( x [ "max" ] ) , f ( x [ "median" ] ) , f ( x [ "mean" ] ) ) for x in data ]
insert_stmt = '''INSERT OR REPLACE INTO ''' + travel_impedance_measure_name + ''' (
                              from_stop_I,
                              to_stop_I,
                              min,
                              max,
                              median,
                              mean) VALUES (?, ?, ?, ?, ?, ?) '''
self . conn . executemany ( insert_stmt , data_tuple )
self . conn . commit ( )


signature:
def plot_trip_counts_per_day ( G , ax = None , highlight_dates = None , highlight_date_labels = None , show = False ) :
    """Parameters
 G : gtfspy . GTFS
 ax : maptlotlib . Axes , optional
 highlight _ dates : list [ str | datetime . datetime ]
 The values of highlight dates should represent dates , and or datetime objects .
 highlight _ date _ labels : list
 The labels for each highlight dates .
 show : bool , optional
 whether or not to immediately show the results
 Returns
 ax : maptlotlib . Axes object"""

implementation:
daily_trip_counts = G . get_trip_counts_per_day ( )
if ax is None :
    _fig , ax = plt . subplots ( )
daily_trip_counts [ "datetime" ] = pandas . to_datetime ( daily_trip_counts [ "date_str" ] )
daily_trip_counts . plot ( "datetime" , "trip_counts" , kind = "line" , ax = ax , marker = "o" , color = "C0" , ls = ":" , label = "Trip counts" )
ax . set_xlabel ( "Date" )
ax . set_ylabel ( "Trip counts per day" )
if highlight_dates is not None :
    assert isinstance ( highlight_dates , list )
    if highlight_date_labels is not None :
        assert isinstance ( highlight_date_labels , list )
        assert len ( highlight_dates ) == len ( highlight_date_labels ) , "Number of highlight date labels do not match"
    else :
        highlight_date_labels = [ None ] * len ( highlight_dates )
    for i , ( highlight_date , label ) in enumerate ( zip ( highlight_dates , highlight_date_labels ) ) :
        color = "C" + str ( int ( i % 8 + 1 ) )
        highlight_date = pandas . to_datetime ( highlight_date )
        ax . axvline ( highlight_date , color = color , label = label )
ax . legend ( loc = "best" )
ax . grid ( )
if show :
    plt . show ( )
return ax


signature:
def make_views ( cls , conn ) :
    """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"""

implementation:
conn . execute ( 'DROP VIEW IF EXISTS main.day_trips' )
conn . execute ( 'CREATE VIEW day_trips AS   ' 'SELECT day_trips2.*, trips.* ' # ' days . day _ start _ ut + trips . start _ time _ ds AS start _ time _ ut , '
# ' days . day _ start _ ut + trips . end _ time _ ds AS end _ time _ ut '
'FROM day_trips2 JOIN trips USING (trip_I);' )
conn . commit ( )
conn . execute ( 'DROP VIEW IF EXISTS main.day_stop_times' )
conn . execute ( 'CREATE VIEW day_stop_times AS   ' 'SELECT day_trips2.*, trips.*, stop_times.*, ' # ' days . day _ start _ ut + trips . start _ time _ ds AS start _ time _ ut , '
# ' days . day _ start _ ut + trips . end _ time _ ds AS end _ time _ ut , '
'day_trips2.day_start_ut+stop_times.arr_time_ds AS arr_time_ut, ' 'day_trips2.day_start_ut+stop_times.dep_time_ds AS dep_time_ut   ' 'FROM day_trips2 ' 'JOIN trips USING (trip_I) ' 'JOIN stop_times USING (trip_I)' )
conn . commit ( )


signature:
def createcolorbar ( cmap , norm ) :
    """Create a colourbar with limits of lwr and upr"""

implementation:
cax , kw = matplotlib . colorbar . make_axes ( matplotlib . pyplot . gca ( ) )
c = matplotlib . colorbar . ColorbarBase ( cax , cmap = cmap , norm = norm )
return c


signature:
def write_walk_transfer_edges ( gtfs , output_file_name ) :
    """Parameters
 gtfs : gtfspy . GTFS
 output _ file _ name : str"""

implementation:
transfers = gtfs . get_table ( "stop_distances" )
transfers . drop ( [ u"min_transfer_time" , u"timed_transfer" ] , 1 , inplace = True )
with util . create_file ( output_file_name , tmpdir = True , keepext = True ) as tmpfile :
    transfers . to_csv ( tmpfile , encoding = 'utf-8' , index = False )


signature:
def write_nodes ( gtfs , output , fields = None ) :
    """Parameters
 gtfs : gtfspy . GTFS
 output : str
 Path to the output file
 fields : list , optional
 which pieces of information to provide"""

implementation:
nodes = gtfs . get_table ( "stops" )
if fields is not None :
    nodes = nodes [ fields ]
with util . create_file ( output , tmpdir = True , keepext = True ) as tmpfile :
    nodes . to_csv ( tmpfile , encoding = 'utf-8' , index = False , sep = ";" )


signature:
def write_stops_geojson ( gtfs , out_file , fields = None ) :
    """Parameters
 gtfs : gtfspy . GTFS
 out _ file : file - like or path to file
 fields : dict
 simultaneously map each original _ name to the new _ name
 Returns"""

implementation:
geojson = create_stops_geojson_dict ( gtfs , fields )
if hasattr ( out_file , "write" ) :
    out_file . write ( json . dumps ( geojson ) )
else :
    with util . create_file ( out_file , tmpdir = True , keepext = True ) as tmpfile_path :
        tmpfile = open ( tmpfile_path , 'w' )
        tmpfile . write ( json . dumps ( geojson ) )


signature:
def write_combined_transit_stop_to_stop_network ( gtfs , output_path , fmt = None ) :
    """Parameters
 gtfs : gtfspy . GTFS
 output _ path : str
 fmt : None , optional
 defaulting to " edg " and writing results as " . edg " files
 If " csv " csv files are produced instead"""

implementation:
if fmt is None :
    fmt = "edg"
multi_di_graph = combined_stop_to_stop_transit_network ( gtfs )
_write_stop_to_stop_network_edges ( multi_di_graph , output_path , fmt = fmt )


signature:
def write_static_networks ( gtfs , output_dir , fmt = None ) :
    """Parameters
 gtfs : gtfspy . GTFS
 output _ dir : ( str , unicode )
 a path where to write
 fmt : None , optional
 defaulting to " edg " and writing results as " . edg " files
 If " csv " csv files are produced instead"""

implementation:
if fmt is None :
    fmt = "edg"
single_layer_networks = stop_to_stop_networks_by_type ( gtfs )
util . makedirs ( output_dir )
for route_type , net in single_layer_networks . items ( ) :
    tag = route_types . ROUTE_TYPE_TO_LOWERCASE_TAG [ route_type ]
    file_name = os . path . join ( output_dir , "network_" + tag + "." + fmt )
    if len ( net . edges ( ) ) > 0 :
        _write_stop_to_stop_network_edges ( net , file_name , fmt = fmt )


signature:
def write_temporal_networks_by_route_type ( gtfs , extract_output_dir ) :
    """Write temporal networks by route type to disk .
 Parameters
 gtfs : gtfspy . GTFS
 extract _ output _ dir : str"""

implementation:
util . makedirs ( extract_output_dir )
for route_type in route_types . TRANSIT_ROUTE_TYPES :
    pandas_data_frame = temporal_network ( gtfs , start_time_ut = None , end_time_ut = None , route_type = route_type )
    tag = route_types . ROUTE_TYPE_TO_LOWERCASE_TAG [ route_type ]
    out_file_name = os . path . join ( extract_output_dir , tag + ".tnet" )
    pandas_data_frame . to_csv ( out_file_name , encoding = 'utf-8' , index = False )


signature:
def write_temporal_network ( gtfs , output_filename , start_time_ut = None , end_time_ut = None ) :
    """Parameters
 gtfs : gtfspy . GTFS
 output _ filename : str
 path to the directory where to store the extracts
 start _ time _ ut : int | None
 start time of the extract in unixtime ( seconds after epoch )
 end _ time _ ut : int | None
 end time of the extract in unixtime ( seconds after epoch )"""

implementation:
util . makedirs ( os . path . dirname ( os . path . abspath ( output_filename ) ) )
pandas_data_frame = temporal_network ( gtfs , start_time_ut = start_time_ut , end_time_ut = end_time_ut )
pandas_data_frame . to_csv ( output_filename , encoding = 'utf-8' , index = False )


signature:
def _write_stop_to_stop_network_edges ( net , file_name , data = True , fmt = None ) :
    """Write out a network
 Parameters
 net : networkx . DiGraph
 base _ name : str
 path to the filename ( without extension )
 data : bool , optional
 whether or not to write out any edge data present
 fmt : str , optional
 If " csv " write out the network in csv format ."""

implementation:
if fmt is None :
    fmt = "edg"
if fmt == "edg" :
    if data :
        networkx . write_edgelist ( net , file_name , data = True )
    else :
        networkx . write_edgelist ( net , file_name )
elif fmt == "csv" :
    with open ( file_name , 'w' ) as f : # writing out the header
        edge_iter = net . edges_iter ( data = True )
        _ , _ , edg_data = next ( edge_iter )
        edg_data_keys = list ( sorted ( edg_data . keys ( ) ) )
        header = ";" . join ( [ "from_stop_I" , "to_stop_I" ] + edg_data_keys )
        f . write ( header )
        for from_node_I , to_node_I , data in net . edges_iter ( data = True ) :
            f . write ( "\n" )
            values = [ str ( from_node_I ) , str ( to_node_I ) ]
            data_values = [ ]
            for key in edg_data_keys :
                if key == "route_I_counts" :
                    route_I_counts_string = str ( data [ key ] ) . replace ( " " , "" ) [ 1 : - 1 ]
                    data_values . append ( route_I_counts_string )
                else :
                    data_values . append ( str ( data [ key ] ) )
            all_values = values + data_values
            f . write ( ";" . join ( all_values ) )


signature:
def write_gtfs ( gtfs , output ) :
    """Write out the database according to the GTFS format .
 Parameters
 gtfs : gtfspy . GTFS
 output : str
 Path where to put the GTFS files
 if output ends with " . zip " a ZIP - file is created instead .
 Returns
 None"""

implementation:
output = os . path . abspath ( output )
uuid_str = "tmp_" + str ( uuid . uuid1 ( ) )
if output [ - 4 : ] == '.zip' :
    zip = True
    out_basepath = os . path . dirname ( os . path . abspath ( output ) )
    if not os . path . exists ( out_basepath ) :
        raise IOError ( out_basepath + " does not exist, cannot write gtfs as a zip" )
    tmp_dir = os . path . join ( out_basepath , str ( uuid_str ) )
    # zip _ file _ na , e = . . / out _ basedir + " . zip
else :
    zip = False
    out_basepath = output
    tmp_dir = os . path . join ( out_basepath + "_" + str ( uuid_str ) )
os . makedirs ( tmp_dir , exist_ok = True )
gtfs_table_to_writer = { "agency" : _write_gtfs_agencies , "calendar" : _write_gtfs_calendar , "calendar_dates" : _write_gtfs_calendar_dates , # fare attributes and fare _ rules omitted ( seldomly used )
"feed_info" : _write_gtfs_feed_info , # " frequencies " : not written , as they are incorporated into trips and routes ,
# Frequencies table is expanded into other tables on initial import . - > Thus frequencies . txt is not created
"routes" : _write_gtfs_routes , "shapes" : _write_gtfs_shapes , "stops" : _write_gtfs_stops , "stop_times" : _write_gtfs_stop_times , "transfers" : _write_gtfs_transfers , "trips" : _write_gtfs_trips , }
for table , writer in gtfs_table_to_writer . items ( ) :
    fname_to_write = os . path . join ( tmp_dir , table + '.txt' )
    print ( fname_to_write )
    writer ( gtfs , open ( os . path . join ( tmp_dir , table + '.txt' ) , 'w' ) )
if zip :
    shutil . make_archive ( output [ : - 4 ] , 'zip' , tmp_dir )
    shutil . rmtree ( tmp_dir )
else :
    print ( "moving " + str ( tmp_dir ) + " to " + out_basepath )
    os . rename ( tmp_dir , out_basepath )


signature:
def _remove_I_columns ( df ) :
    """Remove columns ending with I from a pandas . DataFrame
 Parameters
 df : dataFrame
 Returns
 None"""

implementation:
all_columns = list ( filter ( lambda el : el [ - 2 : ] == "_I" , df . columns ) )
for column in all_columns :
    del df [ column ]


signature:
def _scan_footpaths_to_departure_stop ( self , connection_dep_stop , connection_dep_time , arrival_time_target ) :
    """A helper method for scanning the footpaths . Updates self . _ stop _ profiles accordingly"""

implementation:
for _ , neighbor , data in self . _walk_network . edges_iter ( nbunch = [ connection_dep_stop ] , data = True ) :
    d_walk = data [ 'd_walk' ]
    neighbor_dep_time = connection_dep_time - d_walk / self . _walk_speed
    pt = LabelTimeSimple ( departure_time = neighbor_dep_time , arrival_time_target = arrival_time_target )
    self . _stop_profiles [ neighbor ] . update_pareto_optimal_tuples ( pt )


signature:
def plot_route_network_from_gtfs ( g , ax = None , spatial_bounds = None , map_alpha = 0.8 , scalebar = True , legend = True , return_smopy_map = False , map_style = None ) :
    """Parameters
 g : A gtfspy . gtfs . GTFS object
 Where to get the data from ?
 ax : matplotlib . Axes object , optional
 If None , a new figure and an axis is created
 spatial _ bounds : dict , optional
 with str keys : lon _ min , lon _ max , lat _ min , lat _ max
 return _ smopy _ map : bool , optional
 defaulting to false
 Returns
 ax : matplotlib . axes . Axes"""

implementation:
assert ( isinstance ( g , GTFS ) )
route_shapes = g . get_all_route_shapes ( )
if spatial_bounds is None :
    spatial_bounds = get_spatial_bounds ( g , as_dict = True )
if ax is not None :
    bbox = ax . get_window_extent ( ) . transformed ( ax . figure . dpi_scale_trans . inverted ( ) )
    width , height = bbox . width , bbox . height
    spatial_bounds = _expand_spatial_bounds_to_fit_axes ( spatial_bounds , width , height )
return plot_as_routes ( route_shapes , ax = ax , spatial_bounds = spatial_bounds , map_alpha = map_alpha , plot_scalebar = scalebar , legend = legend , return_smopy_map = return_smopy_map , map_style = map_style )


signature:
def plot_as_routes ( route_shapes , ax = None , spatial_bounds = None , map_alpha = 0.8 , plot_scalebar = True , legend = True , return_smopy_map = False , line_width_attribute = None , line_width_scale = 1.0 , map_style = None ) :
    """Parameters
 route _ shapes : list of dicts that should have the following keys
 name , type , agency , lats , lons
 with types
 list , list , str , list , list
 ax : axis object
 spatial _ bounds : dict
 map _ alpha :
 plot _ scalebar : bool
 legend :
 return _ smopy _ map :
 line _ width _ attribute :
 line _ width _ scale :
 Returns
 ax : matplotlib . axes object"""

implementation:
lon_min = spatial_bounds [ 'lon_min' ]
lon_max = spatial_bounds [ 'lon_max' ]
lat_min = spatial_bounds [ 'lat_min' ]
lat_max = spatial_bounds [ 'lat_max' ]
if ax is None :
    fig = plt . figure ( )
    ax = fig . add_subplot ( 111 )
smopy_map = get_smopy_map ( lon_min , lon_max , lat_min , lat_max , map_style = map_style )
ax = smopy_map . show_mpl ( figsize = None , ax = ax , alpha = map_alpha )
bound_pixel_xs , bound_pixel_ys = smopy_map . to_pixels ( numpy . array ( [ lat_min , lat_max ] ) , numpy . array ( [ lon_min , lon_max ] ) )
route_types_to_lines = { }
for shape in route_shapes :
    route_type = ROUTE_TYPE_CONVERSION [ shape [ 'type' ] ]
    lats = numpy . array ( shape [ 'lats' ] )
    lons = numpy . array ( shape [ 'lons' ] )
    if line_width_attribute :
        line_width = line_width_scale * shape [ line_width_attribute ]
    else :
        line_width = 1
    xs , ys = smopy_map . to_pixels ( lats , lons )
    line , = ax . plot ( xs , ys , linewidth = line_width , color = ROUTE_TYPE_TO_COLOR [ route_type ] , zorder = ROUTE_TYPE_TO_ZORDER [ route_type ] )
    route_types_to_lines [ route_type ] = line
if legend :
    lines = list ( route_types_to_lines . values ( ) )
    labels = [ ROUTE_TYPE_TO_SHORT_DESCRIPTION [ route_type ] for route_type in route_types_to_lines . keys ( ) ]
    ax . legend ( lines , labels , loc = "upper left" )
if plot_scalebar :
    _add_scale_bar ( ax , lat_max , lon_min , lon_max , bound_pixel_xs . max ( ) - bound_pixel_xs . min ( ) )
ax . set_xticks ( [ ] )
ax . set_yticks ( [ ] )
ax . set_xlim ( bound_pixel_xs . min ( ) , bound_pixel_xs . max ( ) )
ax . set_ylim ( bound_pixel_ys . max ( ) , bound_pixel_ys . min ( ) )
if return_smopy_map :
    return ax , smopy_map
else :
    return ax


signature:
def _expand_spatial_bounds_to_fit_axes ( bounds , ax_width , ax_height ) :
    """Parameters
 bounds : dict
 ax _ width : float
 ax _ height : float
 Returns
 spatial _ bounds"""

implementation:
b = bounds
height_meters = util . wgs84_distance ( b [ 'lat_min' ] , b [ 'lon_min' ] , b [ 'lat_max' ] , b [ 'lon_min' ] )
width_meters = util . wgs84_distance ( b [ 'lat_min' ] , b [ 'lon_min' ] , b [ 'lat_min' ] , b [ 'lon_max' ] )
x_per_y_meters = width_meters / height_meters
x_per_y_axes = ax_width / ax_height
if x_per_y_axes > x_per_y_meters : # x - axis
# axis x _ axis has slack - > the spatial longitude bounds need to be extended
    width_meters_new = ( height_meters * x_per_y_axes )
    d_lon_new = ( ( b [ 'lon_max' ] - b [ 'lon_min' ] ) / width_meters ) * width_meters_new
    mean_lon = ( b [ 'lon_min' ] + b [ 'lon_max' ] ) / 2.
    lon_min = mean_lon - d_lon_new / 2.
    lon_max = mean_lon + d_lon_new / 2.
    spatial_bounds = { "lon_min" : lon_min , "lon_max" : lon_max , "lat_min" : b [ 'lat_min' ] , "lat_max" : b [ 'lat_max' ] }
else : # axis y _ axis has slack - > the spatial latitude bounds need to be extended
    height_meters_new = ( width_meters / x_per_y_axes )
    d_lat_new = ( ( b [ 'lat_max' ] - b [ 'lat_min' ] ) / height_meters ) * height_meters_new
    mean_lat = ( b [ 'lat_min' ] + b [ 'lat_max' ] ) / 2.
    lat_min = mean_lat - d_lat_new / 2.
    lat_max = mean_lat + d_lat_new / 2.
    spatial_bounds = { "lon_min" : b [ 'lon_min' ] , "lon_max" : b [ 'lon_max' ] , "lat_min" : lat_min , "lat_max" : lat_max }
return spatial_bounds