示例#1
0
文件: flickr.py 项目: zonakre/gasp
def photos_to_shp(buffer_shp,
                  epsg_in,
                  outshp,
                  keyword=None,
                  epsg_out=4326,
                  apikey=None,
                  onlyInsideInput=True):
    """
    Search for data in Flickr and return a Shapefile with the 
    data.
    """

    from gasp.to.shp import df_to_shp

    photos = photos_location(buffer_shp,
                             epsg_in,
                             keyword=keyword,
                             epsg_out=epsg_out,
                             keyToUse=apikey,
                             onlySearchAreaContained=onlyInsideInput)

    try:
        if not photos: return 0
    except:
        pass

    df_to_shp(photos, outshp)

    return outshp
示例#2
0
文件: feat.py 项目: fagan2888/gasp
def orig_dest_to_polyline(srcPoints, srcField, destPoints, destField, outShp):
    """
    Connect origins to destinations with a polyline which
    length is the minimum distance between the origin related
    with a specific destination.
    
    One origin should be related with one destination.
    These relations should be expressed in srcField and destField
    """

    from geopandas import GeoDataFrame
    from shapely.geometry import LineString
    from gasp.fm import tbl_to_obj
    from gasp.to.shp import df_to_shp

    srcPnt = tbl_to_obj(srcPoints)
    desPnt = tbl_to_obj(destPoints)

    joinDf = srcPnt.merge(destPnt,
                          how='inner',
                          left_on=srcField,
                          right_on=destField)

    joinDf["geometry"] = joinDf.apply(
        lambda x: LineString(x["geometry_x"], x["geometry_y"]), axis=1)

    joinDf.drop(["geometry_x", "geometry_y"], axis=1, inplace=True)

    a = GeoDataFrame(joinDf)

    df_to_shp(joinDf, outShp)

    return outShp
示例#3
0
def tweets_to_shp(buffer_shp,
                  epsg_in,
                  outshp,
                  keyword=None,
                  epsg_out=4326,
                  __encoding__='plain_str',
                  keyAPI=None):
    """
    Search data in Twitter and create a vectorial file with that data
    """

    from gasp.to.shp import df_to_shp

    tweets = geotweets_location(buffer_shp,
                                epsg_in,
                                keyword=keyword,
                                epsg_out=epsg_out,
                                keyToUse=keyAPI,
                                onlySearchAreaContained=None)

    try:
        if not tweets:
            return 0
    except:
        pass

    df_to_shp(tweets, outshp)

    return outshp
示例#4
0
文件: places.py 项目: zonakre/gasp
def find_places(inShp, epsg, radius, output, keyword=None, type=None):
    """
    Extract places from Google Maps
    """

    import pandas
    import time
    from gasp.fm import tbl_to_obj
    from gasp.to.geom import pnt_dfwxy_to_geodf
    from gasp.mng.prj import project
    from gasp.mng.fld.df import listval_to_newcols
    from gasp.to.shp import df_to_shp

    pntDf = tbl_to_obj(inShp)
    pntDf = project(pntDf, None, 4326,
                    gisApi='pandas') if epsg != 4326 else pntDf

    pntDf['latitude'] = pntDf.geometry.y.astype(str)
    pntDf['longitude'] = pntDf.geometry.x.astype(str)

    DATA = 1

    def get_places(row):
        places = get_places_by_radius(row.latitude, row.longitude, radius,
                                      keyword, type)

        if type(DATA) == int:
            DATA = pandas.DataFrame(places['results'])

        else:
            DATA = DATA.append(pandas.DataFrame(places['results']),
                               ignore_index=True)

    a = pntDf.apply(lambda x: get_places(x), axis=1)

    DATA = listval_to_newcols(DATA, 'geometry')
    fldsToDelete = ['viewport', 'opening_hours', 'icon', 'plus_code', 'photos']
    realDeletion = [x for x in fldsToDelete if x in DATA.columns.values]
    DATA.drop(realDeletion, axis=1, inplace=True)

    DATA = listval_to_newcols(DATA, 'location')

    DATA = pnt_dfwxy_to_geodf(DATA, 'lng', 'lat', 4326)

    if epsg != 4326:
        DATA = project(DATA, None, epsg, gisApi='pandas')

    DATA["types"] = DATA.types.astype(str)

    df_to_shp(DATA, output)

    return output
示例#5
0
文件: inebgri.py 项目: zonakre/gasp
def join_bgrishp_with_bgridata(bgriShp,
                               bgriCsv,
                               outShp,
                               shpJoinField="BGRI11",
                               dataJoinField="GEO_COD",
                               joinFieldsMantain=None,
                               newNames=None):
    """
    Join BGRI ESRI Shapefile with the CSV with the BGRI Data
    """

    from gasp import goToList
    from gasp.fm import tbl_to_obj
    from gasp.to.shp import df_to_shp

    # Read main_table
    mainDf = tbl_to_obj(bgriShp)

    # Read join table
    joinDf = tbl_to_obj(bgriCsv, _delimiter=';', encoding_='utf-8')

    # Sanitize GEO_COD of bgriCsv
    joinDf[dataJoinField] = joinDf[dataJoinField].str.replace("'", "")

    if joinFieldsMantain:
        joinFieldsMantain = goToList(joinFieldsMantain)

        dropCols = []
        for col in joinDf.columns.values:
            if col not in [dataJoinField] + joinFieldsMantain:
                dropCols.append(col)

        joinDf.drop(dropCols, axis=1, inplace=True)

    resultDf = mainDf.merge(joinDf,
                            how='inner',
                            left_on=shpJoinField,
                            right_on=dataJoinField)
    if newNames:
        newNames = goToList(newNames)
        renDict = {
            joinFieldsMantain[n]: newNames[n]
            for n in range(len(joinFieldsMantain))
        }

        resultDf.rename(columns=renDict, inplace=True)

    df_to_shp(resultDf, outShp)

    return outShp
示例#6
0
def intersection(inShp, intersectShp, outShp, api='geopandas'):
    """
    Intersection between ESRI Shapefile
    
    'API's Available:
    * geopandas
    * saga;
    * pygrass
    """

    if api == 'geopandas':
        import geopandas

        from gasp.fm import tbl_to_obj
        from gasp.to.shp import df_to_shp

        dfShp = tbl_to_obj(inShp)
        dfIntersect = tbl_to_obj(intersectShp)

        res_interse = geopandas.overlay(dfShp, dfIntersect, how='intersection')

        df_to_shp(res_interse, outShp)

    elif api == 'saga':
        from gasp import exec_cmd

        cmdout = exec_cmd(
            ("saga_cmd shapes_polygons 14 -A {} -B {} -RESULT {} -SPLIT 1"
             ).format(inShp, intersectShp, outShp))

    elif api == 'pygrass':
        from grass.pygrass.modules import Module

        clip = Module("v.overlay",
                      ainput=inShp,
                      atype="area",
                      binput=intersectShp,
                      btype="area",
                      operator="and",
                      output=outShp,
                      overwrite=True,
                      run_=False,
                      quiet=True)

        clip()

    else:
        raise ValueError("{} is not available!".format(api))

    return outShp
示例#7
0
def merge_feat(shps, outShp, api="ogr2ogr"):
    """
    Get all features in several Shapefiles and save them in one file
    """
    
    if api == "ogr2ogr":
        from gasp         import exec_cmd
        from gasp.prop.ff import drv_name
        
        out_drv = drv_name(outShp)
        
        # Create output and copy some features of one layer (first in shps)
        cmdout = exec_cmd('ogr2ogr -f "{}" {} {}'.format(
            out_drv, outShp, shps[0]
        ))
        
        # Append remaining layers
        lcmd = [exec_cmd(
            'ogr2ogr -f "{}" -update -append {} {}'.format(
                out_drv, outShp, shps[i]
            )
        ) for i in range(1, len(shps))]
    
    elif api == 'pandas':
        """
        Merge SHP using pandas
        """
        
        from gasp.fm     import tbl_to_obj
        from gasp.to.shp import df_to_shp
        
        if type(shps) != list:
            raise ValueError('shps should be a list with paths for Feature Classes')
        
        dfs = [tbl_to_obj(shp) for shp in shps]
        
        result = dfs[0]
        
        for df in dfs[1:]:
            result = result.append(df, ignore_index=True, sort=True)
        
        df_to_shp(result, outShp)
    
    else:
        raise ValueError(
            "{} API is not available"
        )
    
    return outShp
示例#8
0
def split_shp_by_attr(inShp, attr, outDir, _format='.shp'):
    """
    Create a new shapefile for each value in a column
    """

    import os
    from gasp.fm import shp_to_df
    from gasp.oss import get_filename
    from gasp.mng.fld.df import col_distinct
    from gasp.to.shp import df_to_shp

    # Sanitize format
    FFF = _format if _format[0] == '.' else '.' + _format

    # SHP TO DF
    dataDf = tbl_to_obj(inShp)

    # Get values in attr
    uniqueAttr = col_distinct(dataDf, attr)

    # Export Features with the same value in attr to a new File
    BASENAME = get_filename(inShp, forceLower=True)
    SHPS_RESULT = {}
    i = 1
    for val in uniqueAttr:
        df = dataDf[dataDf[attr] == val]

        newShp = df_to_shp(
            df, os.path.join(outDir, "{}_{}{}".format(BASENAME, str(i), FFF)))

        SHPS_RESULT[val] = newShp

        i += 1

    return SHPS_RESULT
示例#9
0
def path_from_coords_to_shp(latOrigin, lngOrigin, latDest, lngDest, outshp,
                            transmod='foot-walking', outepsg=4326):
    """
    Receive coords and get path. Save path as Feature Class
    """
    
    import pandas
    from gasp.web.orouteserv import directions
    from gasp.to.geom        import regulardf_to_geodf, json_obj_to_geodf
    from gasp.to.shp         import df_to_shp
    
    path = directions(
        latOrigin, lngOrigin, latDest, lngDest,
        modeTransportation=transmod
    )
    
    geodf = json_obj_to_geodf(path, 4326)
    
    geodf.drop(['segments', 'bbox', 'way_points'], axis=1, inplace=True)
    
    geodf["summary"] = geodf['summary'][0]
    
    geodf = pandas.concat([
        geodf.drop(['summary'], axis=1),
        geodf['summary'].apply(pandas.Series)
    ], axis=1)
    
    geodf = regulardf_to_geodf(geodf, "geometry", 4326)
    
    if outepsg != 4326:
        from gasp.mng.prj import project
        geodf = project(geodf, None, outepsg, gisApi='pandas')
    
    return df_to_shp(geodf, outshp)
示例#10
0
文件: bf.py 项目: zonakre/gasp
def geodf_buffer_to_shp(geoDf, dist, outfile, colgeom='geometry'):
    """
    Execute the Buffer Function of GeoPandas and export
    the result to a new shp
    """

    from gasp.to.shp import df_to_shp

    __geoDf = geoDf.copy()
    __geoDf["buffer_geom"] = __geoDf[colgeom].buffer(dist, resolution=16)

    __geoDf.drop(colgeom, axis=1, inplace=True)
    __geoDf.rename(columns={"buffer_geom": colgeom}, inplace=True)

    df_to_shp(__geoDf, outfile)

    return outfile
示例#11
0
文件: __init__.py 项目: zonakre/gasp
def pointXls_to_shp(xlsFile, outShp, x_col, y_col, epsg, sheet=None):
    """
    Excel table with Point information to ESRI Shapefile
    """

    from gasp.fm import tbl_to_obj
    from gasp.to.geom import pnt_dfwxy_to_geodf
    from gasp.to.shp import df_to_shp

    # XLS TO PANDAS DATAFRAME
    dataDf = tbl_to_obj(xlsFile, sheet=sheet)

    # DATAFRAME TO GEO DATAFRAME
    geoDataDf = pnt_dfwxy_to_geodf(dataDf, x_col, y_col, epsg)

    # GEODATAFRAME TO ESRI SHAPEFILE
    df_to_shp(geoDataDf, outShp)

    return outShp
示例#12
0
def places_to_shp(searchArea, epsgIn, epsgOut, outShp,
                  keyword_=None, onlySearchArea=True):
    """
    Get Locations From Facebook and Write data in a Vetorial
    File
    """
    
    from gasp.to.shp import df_to_shp
    
    places = places_by_query(
        searchArea, epsgIn, keyword=keyword_, epsgOut=epsgOut,
        onlySearchAreaContained=onlySearchArea
    )
    
    try:
        if not places: return 0
    except:
        pass
    
    df_to_shp(places, outShp)
    
    return outShp
示例#13
0
文件: genze.py 项目: zonakre/gasp
def pnd_dissolve(shp, field, outShp):
    """
    Dissolve using GeoPandas
    """

    from gasp.fm import tbl_to_obj
    from gasp.to.shp import df_to_shp

    df = tbl_to_obj(shp)

    dissDf = df.dissolve(by=field)

    return df_to_shp(df, outShp)
示例#14
0
文件: __init__.py 项目: zonakre/gasp
def psql_to_shp(conParam,
                table,
                outshp,
                api='pandas',
                epsg=None,
                geom_col='geom',
                tableIsQuery=None):
    """
    PostgreSQL table to ESRI Shapefile using Pandas or PGSQL2SHP
    """

    if api == 'pandas':
        from gasp.fm.sql import psql_to_geodf
        from gasp.to.shp import df_to_shp

        q = "SELECT * FROM {}".format(table) if not tableIsQuery else table

        df = psql_to_geodf(conParam, q, geomCol=geom_col, epsg=epsg)

        outsh = df_to_shp(df, outshp)

    elif api == 'pgsql2shp':
        from gasp import exec_cmd

        cmd = ('pgsql2shp -f {out} -h {hst} -u {usr} -p {pt} -P {pas}{geom} '
               '{bd} {t}').format(
                   hst=conParam['HOST'],
                   usr=conParam['USER'],
                   pt=conParam['PORT'],
                   pas=conParam['PASSWORD'],
                   bd=conParam['DATABASE'],
                   t=table if not tableIsQuery else '"{}"'.format(table),
                   out=outshp,
                   geom="" if not geom_col else " -g {}".format(geom_col))

        outcmd = exec_cmd(cmd)

    else:
        raise ValueError('api value must be \'pandas\' or \'pgsql2shp\'')

    return outshp
示例#15
0
def same_attr_to_shp(inShps, interestCol, outFolder, basename="data_",
                     resultDict=None):
    """
    For several SHPS with the same field, this program will list
    all values in such field and will create a new shp for all
    values with the respective geometry regardeless the origin shp.
    """
    
    import os
    from gasp         import goToList
    from gasp.fm      import tbl_to_obj
    from gasp.mng.gen import merge_df
    from gasp.to.shp  import df_to_shp
    
    EXT = os.path.splitext(inShps[0])[1]
    
    shpDfs = [tbl_to_obj(shp) for shp in inShps]
    
    DF = merge_df(shpDfs, ignIndex=True)
    #DF.dropna(axis=0, how='any', inplace=True)
    
    uniqueVal = DF[interestCol].unique()
    
    nShps = [] if not resultDict else {}
    for val in uniqueVal:
        ndf = DF[DF[interestCol] == val]
        
        KEY = str(val).split('.')[0] if '.' in str(val) else str(val)
        
        nshp = df_to_shp(ndf, os.path.join(
            outFolder, '{}{}{}'.format(basename, KEY, EXT)
        ))
        
        if not resultDict:
            nShps.append(nshp)
        else:
            nShps[KEY] = nshp
    
    return nShps
示例#16
0
def df_buffer_extent(inShp, inEpsg, meterTolerance, outShp):
    """
    For all geometries, calculate the boundary given by 
    the sum between the feature extent and the Tolerance variable
    """

    from shapely.geometry import Polygon
    from geopandas import GeoDataFrame
    from gasp.fm import tbl_to_obj
    from gasp.to.shp import df_to_shp

    inDf = tbl_to_obj(inShp)

    inDf = df_add_ext(inDf, "geometry")

    inDf['minx'] = inDf.minx - meterTolerance
    inDf['miny'] = inDf.miny - meterTolerance
    inDf['maxx'] = inDf.maxx + meterTolerance
    inDf['maxy'] = inDf.maxy + meterTolerance

    # Produce new geometries
    geoms = [
        Polygon([[ext[0], ext[3]], [ext[1], ext[3]], [ext[1], ext[2]],
                 [ext[0], ext[2]], [ext[0], ext[3]]])
        for ext in zip(inDf.minx, inDf.maxx, inDf.miny, inDf.maxy)
    ]

    inDf.drop(['minx', 'miny', 'maxx', 'maxy', 'geometry'],
              axis=1,
              inplace=True)

    result = GeoDataFrame(inDf,
                          crs={'init': 'epsg:{}'.format(inEpsg)},
                          geometry=geoms)

    return df_to_shp(inDf, outShp)
示例#17
0
文件: mapbx.py 项目: zonakre/gasp
def matrix_od(originsShp, destinationShp, originsEpsg, destinationEpsg,
              resultShp, modeTrans="driving"):
    """
    Use Pandas to Retrieve data from MapBox Matrix OD Service
    """
    
    import time
    from threading       import Thread
    from gasp.web.mapbx  import get_keys, matrix
    from gasp.fm         import tbl_to_obj
    from gasp.mng.split  import split_df, split_df_inN
    from gasp.mng.fld.df import listval_to_newcols
    from gasp.fm.geom    import pointxy_to_cols
    from gasp.mng.prj    import project
    from gasp.mng.gen    import merge_df
    from gasp.prop.feat  import get_geom_type
    from gasp.to.shp     import df_to_shp
    
    # Data to GeoDataFrame
    origens  = tbl_to_obj(    originsShp)
    destinos = tbl_to_obj(destinationShp)
    
    # Check if SHPs are points
    inGeomType = get_geom_type(origens, geomCol="geometry", gisApi='pandas')
    
    if inGeomType != 'Point' and inGeomType != 'MultiPoint':
        raise ValueError('The input geometry must be of type point')
    
    inGeomType = get_geom_type(destinos, geomCol="geometry", gisApi='pandas')
    
    if inGeomType != 'Point' and inGeomType != 'MultiPoint':
        raise ValueError('The input geometry must be of type point')
    
    # Re-Project data to WGS
    if originsEpsg != 4326:
        origens = project(origens, None, 4326, gisApi='pandas')
    
    if destinationEpsg != 4326:
        destinos = project(destinos, None, 4326, gisApi='pandas')
    
    origens = pointxy_to_cols(
        origens, geomCol="geometry",
        colX="longitude", colY="latitude"
    ); destinos = pointxy_to_cols(
        destinos, geomCol="geometry",
        colX="longitude", colY="latitude"
    )
    
    # Prepare coordinates Str
    origens["location"]  = origens.longitude.astype(str) \
        + "," + origens.latitude.astype(str)
    
    destinos["location"] = destinos.longitude.astype(str) \
        + "," + destinos.latitude.astype(str)
    
    # Split destinations DataFrame into Dafaframes with
    # 24 rows
    lst_destinos = split_df(destinos, 24)
    
    # Get Keys to use
    KEYS = get_keys()
    # Split origins by key
    origensByKey = split_df_inN(origens, KEYS.shape[0])
    
    lst_keys= KEYS["key"].tolist()
    
    # Produce matrix
    results = []
    def get_matrix(origins, key):
        def def_apply(row):
            rowResults = []
            for df in lst_destinos:
                strDest = df.location.str.cat(sep=";")
                
                strLocations = row["location"] + ";" + strDest
                
                dados = matrix(
                    strLocations, idxSources="0",
                    idxDestinations=";".join([str(i) for i in range(1, df.shape[0] + 1)]),
                    useKey=key, modeTransportation=modeTrans
                )
                time.sleep(5)
                
                rowResults += dados["durations"][0]
            
            row["od_matrix"] = rowResults
            
            return row
        
        newOrigins = origins.apply(
            lambda x: def_apply(x), axis=1
        )
        
        results.append(newOrigins)
    
    # Create threads
    thrds = []
    i     = 1
    for df in origensByKey:
        thrds.append(Thread(
            name="tk{}".format(str(i)), target=get_matrix,
            args=(df, lst_keys[i - 1])
        ))
        i += 1
    
    # Start all threads
    for thr in thrds:
        thr.start()
    
    # Wait for all threads to finish
    for thr in thrds:
        thr.join()
    
    # Join all dataframes
    RESULT = merge_df(results, ignIndex=False)
    
    RESULT = listval_to_newcols(RESULT, "od_matrix")
    
    RESULT.rename(
        columns={
            c: "dest_{}".format(c)
            for c in RESULT.columns.values if type(c) == int or type(c) == long
        }, inplace=True
    )
    
    if originsEpsg != 4326:
        RESULT = project(RESULT, None, originsEpsg, gisApi='pandas')
    
    return df_to_shp(RESULT, resultShp)


    
    return results
示例#18
0
文件: popaccess.py 项目: zonakre/gasp
def pop_less_dist_x2(net_dataset,
                     rdv_name,
                     locations,
                     interval,
                     unities,
                     fld_groups,
                     fld_pop,
                     w,
                     output,
                     useOneway=None):
    """
    Network processing - executar service area de modo a conhecer as areas a
    menos de x minutos de qualquer coisa
    """

    import arcpy
    import numpy
    import os
    import pandas
    from gasp.cpu.arcg.lyr import feat_lyr
    from gasp.mng.genze import dissolve
    from gasp.cpu.arcg.anls.ovlay import intersect
    from gasp.cpu.arcg.mng.fld import calc_fld
    from gasp.mob.arctbx.svarea import service_area_polygon
    from gasp.fm import tbl_to_obj
    from gasp.oss import get_filename
    from gasp.to.shp import df_to_shp
    from gasp.cpu.arcg.mng.fld import del_field

    if arcpy.CheckExtension("Network") == "Available":
        arcpy.CheckOutExtension("Network")
    # Procedure #
    # Generate Service Area
    svArea = service_area_polygon(net_dataset,
                                  rdv_name,
                                  interval,
                                  locations,
                                  os.path.join(w, "servarea.shp"),
                                  ONEWAY_RESTRICTION=useOneway)

    # Dissolve Service Area
    svArea = dissolve(svArea,
                      os.path.join(w, 'svarea_diss.shp'),
                      "FID",
                      api="arcpy")

    # Intersect unities with Service Area
    lyr_unities = feat_lyr(unities)
    unities_servarea = intersect([lyr_unities, svArea],
                                 os.path.join(w, "unidades_mx.shp"))

    # In the original Unities SHP, create a col with the population
    # only for the unities intersected with service area
    intersectDf = tbl_to_obj(unities_servarea)

    unities_less_than = intersectDf[fld_pop].unique()
    unities_less_than = pandas.DataFrame(unities_less_than, columns=['cod_'])

    popDf = tbl_to_obj(unities)
    popDf = popDf.merge(unities_less_than,
                        how='outer',
                        left_on=fld_pop,
                        right_on="cod_")
    popDf["less_than"] = popDf.cod_.fillna(value='0')
    popDf["less_than"] = numpy.where(popDf["less_than"] != '0', '1', '0')
    popDf["population"] = numpy.where(popDf["less_than"] == '1',
                                      popDf[fld_pop], 0)
    popDf["original"] = popDf[fld_pop]

    newUnities = df_to_shp(popDf, os.path.join(w, 'unities_pop.shp'))

    # Dissolve and Get result
    result = dissolve(newUnities,
                      output,
                      fld_groups,
                      statistics="original SUM;population SUM",
                      api="arcpy")

    calc_fld(result, "pop_{}".format(interval), "[SUM_popula]", {
        "TYPE": "INTEGER",
        "LENGTH": "10",
        "PRECISION": ""
    })

    calc_fld(result, fld_pop, "[SUM_origin]", {
        "TYPE": "INTEGER",
        "LENGTH": "10",
        "PRECISION": ""
    })

    calc_fld(result, "pop_{}_p".format(interval),
             "([pop_{}] / [{}]) *100".format(interval, fld_pop), {
                 "TYPE": "DOUBLE",
                 "LENGTH": "6",
                 "PRECISION": "2"
             })

    del_field(result, "SUM_popula")
    del_field(result, "SUM_origin")

    return result
示例#19
0
def servarea_from_points(pntShp, inEPSG, range, outShp,
                         mode='foot-walking', intervals=None):
    """
    Calculate isochrones for all points in a Point Feature Class
    """
    
    import time
    from shapely.geometry    import shape
    from threading           import Thread
    from gasp.web.orouteserv import get_keys, isochrones
    from gasp.fm             import tbl_to_obj
    from gasp.mng.split      import split_df_inN
    from gasp.fm.geom        import pointxy_to_cols
    from gasp.mng.gen        import merge_df
    from gasp.prop.feat      import get_geom_type
    from gasp.mng.prj        import project
    from gasp.to.geom        import dict_to_geodf
    from gasp.to.obj         import df_to_dict
    from gasp.to.shp         import df_to_shp
    
    # SHP TO GEODATAFRAME
    pntDf = tbl_to_obj(pntShp)
    
    # Check if SHPs are points
    inGeomType = get_geom_type(pntDf, geomCol="geometry", gisApi='pandas')
    
    if inGeomType != 'Point' and inGeomType != 'MultiPoint':
        raise ValueError('The input geometry must be of type point')
    
    # Reproject geodf if necessary
    if inEPSG != 4326:
        pntDf = project(pntDf, None, 4326, gisApi='pandas')
    
    pntDf["old_fid"] = pntDf.index
    
    pntDf = pointxy_to_cols(
        pntDf, geomCol="geometry",
        colX="longitude", colY="latitude"
    )
    
    # Get Keys
    KEYS = get_keys()
    
    df_by_key = split_df_inN(pntDf, KEYS.shape[0])
    
    keys_list = KEYS['key'].tolist()
    
    results = []
    
    def get_isochrones(df, key):
        pntDict = df_to_dict(df)
    
        for k in pntDict:
            iso = isochrones(
                "{},{}".format(pntDict[k]["longitude"], pntDict[k]["latitude"]),
                range, range_type='time', modeTransportation=mode,
                intervals=intervals
            )
        
            pntDict[k]["geometry"] = shape(iso["features"][0]["geometry"])
        
            time.sleep(5)
    
            pntDf = dict_to_geodf(pntDict, "geometry", 4326)
        
        results.append(pntDf)
    
    # Create threads
    thrds = []
    i = 1
    for df in df_by_key:
        thrds.append(Thread(
            name='tk{}'.format(str(i)), target=get_isochrones,
            args=(df, keys_list[i - 1])
        ))
        i += 1
    
    # Start all threads
    for thr in thrds:
        thr.start()
    
    # Wait for all threads to finish
    for thr in thrds:
        thr.join()
    
    # Join all dataframes
    pntDf = merge_df(results, ignIndex=False)
    
    if inEPSG != 4326:
        pntDf = project(pntDf, None, inEPSG, gisApi='pandas')
    
    return df_to_shp(pntDf, outShp)
示例#20
0
文件: popaccess.py 项目: zonakre/gasp
def population_within_point_buffer(netDataset,
                                   rdvName,
                                   pointShp,
                                   populationShp,
                                   popField,
                                   bufferDist,
                                   epsg,
                                   output,
                                   workspace=None,
                                   bufferIsTimeMinutes=None,
                                   useOneway=None):
    """
    Assign to points the population within a certain distance (metric or time)
    
    * Creates a Service Area Polygon for each point in pointShp;
    * Intersect the Service Area Polygons with the populationShp;
    * Count the number of persons within each Service Area Polygon
    (this number will be weighted by the area % of the statistic unit
    intersected with the Service Area Polygon).
    """

    import arcpy
    import os
    from geopandas import GeoDataFrame
    from gasp.cpu.arcg.lyr import feat_lyr
    from gasp.cpu.arcg.anls.ovlay import intersect
    from gasp.mng.gen import copy_feat
    from gasp.cpu.arcg.mng.fld import add_geom_attr
    from gasp.cpu.arcg.mng.fld import add_field
    from gasp.cpu.arcg.mng.fld import calc_fld
    from gasp.mng.genze import dissolve
    from gasp.mob.arctbx.svarea import service_area_use_meters
    from gasp.mob.arctbx.svarea import service_area_polygon
    from gasp.fm import tbl_to_obj
    from gasp.to.shp import df_to_shp

    workspace = os.path.dirname(pointShp) if not workspace else workspace

    if not os.path.exists(workspace):
        from gasp.oss.ops import create_folder
        workspace = create_folder(workspace, overwrite=False)

    # Copy population layer
    populationShp = copy_feat(
        populationShp,
        os.path.join(workspace,
                     'cop_{}'.format(os.path.basename(populationShp))),
        gisApi='arcpy')

    # Create layer
    pntLyr = feat_lyr(pointShp)
    popLyr = feat_lyr(populationShp)

    # Create Service Area
    if not bufferIsTimeMinutes:
        servArea = service_area_use_meters(
            netDataset,
            rdvName,
            bufferDist,
            pointShp,
            os.path.join(workspace,
                         'servare_{}'.format(os.path.basename(pointShp))),
            OVERLAP=False,
            ONEWAY=useOneway)

    else:
        servArea = service_area_polygon(
            netDataset,
            rdvName,
            bufferDist,
            pointShp,
            os.path.join(workspace,
                         "servare_{}".format(os.path.basename(pointShp))),
            ONEWAY_RESTRICTION=useOneway,
            OVERLAP=None)

    servAreaLyr = feat_lyr(servArea)

    # Add Column with Polygons area to Feature Class population
    add_geom_attr(popLyr, "total", geom_attr="AREA")

    # Intersect buffer and Population Feature Class
    intSrc = intersect([servAreaLyr, popLyr],
                       os.path.join(workspace, "int_servarea_pop.shp"))

    intLyr = feat_lyr(intSrc)

    # Get area of intersected statistical unities with population
    add_geom_attr(intLyr, "partarea", geom_attr="AREA")

    # Get population weighted by area intersected
    calc_fld(intLyr, "population",
             "((([partarea] * 100) / [total]) * [{}]) / 100".format(popField),
             {
                 "TYPE": "DOUBLE",
                 "LENGTH": "10",
                 "PRECISION": "3"
             })

    # Dissolve service area by Facility ID
    diss = dissolve(intLyr,
                    os.path.join(workspace, 'diss_servpop.shp'),
                    "FacilityID",
                    statistics="population SUM")

    # Get original Point FID from FacilityID
    calc_fld(diss, "pnt_fid", "[FacilityID] - 1", {
        "TYPE": "INTEGER",
        "LENGTH": "5",
        "PRECISION": None
    })

    dfPnt = tbl_to_obj(pointShp)
    dfDiss = tbl_to_obj(diss)

    dfDiss.rename(columns={"SUM_popula": "n_pessoas"}, inplace=True)

    resultDf = dfPnt.merge(dfDiss,
                           how='inner',
                           left_index=True,
                           right_on="pnt_fid")

    resultDf.drop('geometry_y', axis=1, inplace=True)

    resultDf = GeoDataFrame(resultDf,
                            crs={'init': 'epsg:{}'.format(epsg)},
                            geometry='geometry_x')

    df_to_shp(resultDf, output)

    return output
示例#21
0
def project(inShp, outShp, outEPSG, inEPSG=None, gisApi='ogr', sql=None):
    """
    Project Geodata using GIS
    
    API's Available:
    * arcpy
    * ogr
    * ogr2ogr;
    * pandas
    """
    import os
    
    if gisApi == 'arcpy':
        """
        Execute Data Management > Data Transformations > Projection
        """
        
        import arcpy
        from gasp.cpu.arcg.lyr import feat_lyr
        from gasp.web.srorg    import get_wkt_esri
        
        layer   = feat_lyr(inShp)
        srs_obj = get_wkt_esri(outEPSG)
        
        arcpy.Project_management(layer, outShp, srs_obj)
    
    elif gisApi == 'ogr':
        """
        Using ogr Python API
        """
        
        if not inEPSG:
            raise ValueError(
                'To use ogr API, you should specify the EPSG Code of the'
                ' input data using inEPSG parameter'
            )
        
        from osgeo          import ogr
        from gasp.prop.feat import get_geom_type
        from gasp.prop.ff   import drv_name
        from gasp.mng.fld   import ogr_copy_fields
        from gasp.prop.prj  import get_sref_from_epsg
        from gasp.oss       import get_filename
        
        def copyShp(out, outDefn, lyr_in, trans):
            for f in lyr_in:
                g = f.GetGeometryRef()
                g.Transform(trans)
                new = ogr.Feature(outDefn)
                new.SetGeometry(g)
                for i in range(0, outDefn.GetFieldCount()):
                    new.SetField(outDefn.GetFieldDefn(i).GetNameRef(), f.GetField(i))
                out.CreateFeature(new)
                new.Destroy()
                f.Destroy()
        
        # ####### #
        # Project #
        # ####### #
        transP = get_trans_param(inEPSG, outEPSG)
        
        inData = ogr.GetDriverByName(
            drv_name(inShp)).Open(inShp, 0)
        
        inLyr = inData.GetLayer()
        out = ogr.GetDriverByName(
            drv_name(outShp)).CreateDataSource(outShp)
        
        outlyr = out.CreateLayer(
            get_filename(outShp), get_sref_from_epsg(outEPSG),
            geom_type=get_geom_type(
                inShp, name=None, py_cls=True, gisApi='ogr'
            )
        )
        
        # Copy fields to the output
        ogr_copy_fields(inLyr, outlyr)
        # Copy/transform features from the input to the output
        outlyrDefn = outlyr.GetLayerDefn()
        copyShp(outlyr, outlyrDefn, inLyr, transP)
        
        inData.Destroy()
        out.Destroy()
    
    elif gisApi == 'ogr2ogr':
        """
        Transform SRS of any OGR Compilant Data. Save the transformed data
        in a new file
    
        TODO: DB - only works with sqlite
        """
        
        if not inEPSG:
            raise ValueError('To use ogr2ogr, you must specify inEPSG')
        
        from gasp         import exec_cmd
        from gasp.prop.ff import drv_name
        
        cmd = (
            'ogr2ogr -f "{}" {} {}{} -s_srs EPSG:{} -t_srs:{}'
        ).format(
            drv_name(outShp), outShp, inShp,
            '' if not sql else ' -dialect sqlite -sql "{}"'.format(sql),
            str(inEpsg), str(outEpsg)
        )
        
        outcmd = exec_cmd(cmd)
    
    elif gisApi == 'pandas':
        # Test if input Shp is GeoDataframe
        from geopandas import GeoDataFrame as gdf
        
        if type(inShp) == gdf:
            # Is DataFrame
            df = inShp
        
        else:
            # Assuming is file
            if os.path.exists(inShp):
                # Is File 
                from gasp.fm import tbl_to_obj
                
                df = tbl_to_obj(inShp)
            else:
                raise ValueError((
                    "For pandas API, inShp must be file or GeoDataFrame"
                ))
        
        # Project df
        newDf = df.to_crs({'init' : 'epsg:{}'.format(str(outEPSG))})
        
        if outShp:
            # Try to save as file
            from gasp.to.shp import df_to_shp
            
            return df_to_shp(df, outShp)
        
        else:
            return newDf
    
    else:
        raise ValueError('Sorry, API {} is not available'.format(gisApi))
    
    return outShp
示例#22
0
文件: __init__.py 项目: zonakre/gasp
def obj_to_shp(dd, geomkey, srs, outshp):
    from gasp.to.obj import obj_to_geodf

    geodf = obj_to_geodf(dd, geomkey, srs)

    return df_to_shp(geodf, outshp)
示例#23
0
文件: tplgy.py 项目: zonakre/gasp
def snap_points_to_near_line(lineShp, pointShp, epsg, workGrass,
                             outPoints, location='overlap_pnts', api='grass',
                             movesShp=None):
    """
    Move points to overlap near line
    
    API's Available:
    * grass;
    * saga.
    """
    
    if api == 'grass':
        """
        Uses GRASS GIS to find near lines.
        """
        
        import os;        import numpy
        from geopandas    import GeoDataFrame
        from gasp.oss     import get_filename
        from gasp.session import run_grass
        from gasp.fm      import shp_to_df
        from gasp.to.shp  import df_to_shp
    
        # Create GRASS GIS Location
        grassBase = run_grass(workGrass, location=location, srs=epsg)
    
        import grass.script as grass
        import grass.script.setup as gsetup
        gsetup.init(grassBase, workGrass, location, 'PERMANENT')
    
        # Import some GRASS GIS tools
        from gasp.anls.prox        import grs_near as near
        from gasp.cpu.grs.mng.feat import geomattr_to_db
        from gasp.to.shp.grs       import shp_to_grs, grs_to_shp
    
        # Import data into GRASS GIS
        grsLines = shp_to_grs(
            lineShp, get_filename(lineShp, forceLower=True)
        )
    
        grsPoint = shp_to_grs(
            pointShp, get_filename(pointShp, forceLower=True)
        )
    
        # Get distance from points to near line
        near(grsPoint, grsLines, nearCatCol="tocat", nearDistCol="todistance")
    
        # Get coord of start/end points of polylines
        geomattr_to_db(grsLines, ['sta_pnt_x', 'sta_pnt_y'], 'start', 'line')
        geomattr_to_db(grsLines, ['end_pnt_x', 'end_pnt_y'],   'end', 'line')
    
        # Export data from GRASS GIS
        ogrPoint = grs_to_shp(grsPoint, os.path.join(
            workGrass, grsPoint + '.shp', 'point', asMultiPart=True
        ))

        ogrLine = grs_to_shp(grsLines, os.path.join(
            workGrass, grsLines + '.shp', 'point', asMultiPart=True
        ))
    
        # Points to GeoDataFrame
        pntDf = tbl_to_obj(ogrPoint)
        # Lines to GeoDataFrame
        lnhDf = tbl_to_obj(ogrLine)
    
        # Erase unecessary fields
        pntDf.drop(["todistance"], axis=1, inplace=True)
        lnhDf.drop([c for c in lnhDf.columns.values if c != 'geometry' and 
                    c != 'cat' and c != 'sta_pnt_x' and c != 'sta_pnt_y' and 
                    c != 'end_pnt_x' and c != 'end_pnt_y'],
                    axis=1, inplace=True)
    
        # Join Geometries - Table with Point Geometry and Geometry of the 
        # nearest line
        resultDf = pntDf.merge(
            lnhDf, how='inner', left_on='tocat', right_on='cat')
    
        # Move points
        resultDf['geometry'] = [geoms[0].interpolate(
            geoms[0].project(geoms[1])
        ) for geoms in zip(resultDf.geometry_y, resultDf.geometry_x)]
    
        resultDf.drop(["geometry_x", "geometry_y", "cat_x", "cat_y"],
                      axis=1, inplace=True)
    
        resultDf = GeoDataFrame(
            resultDf, crs={"init" : 'epsg:{}'.format(epsg)}, geometry="geometry"
        )
    
        # Check if points are equal to any start/end points
        resultDf["x"] = resultDf.geometry.x
        resultDf["y"] = resultDf.geometry.y
    
        resultDf["check"] = numpy.where(
            (resultDf["x"] == resultDf["sta_pnt_x"]) & (resultDf["y"] == resultDf["sta_pnt_y"]),
            1, 0
        )
    
        resultDf["check"] = numpy.where(
            (resultDf["x"] == resultDf["end_pnt_x"]) & (resultDf["y"] == resultDf["end_pnt_y"]),
            1, 0
        )
    
        # To file
        df_to_shp(resultDf, outPoints)
    
    elif api == 'saga':
        """
        Snap Points to Lines using SAGA GIS
        """
        
        from gasp import exec_cmd
        
        cmd = (
            "saga_cmd shapes_points 19 -INPUT {pnt} -SNAP {lnh} "
            "-OUTPUT {out}{mv}"
        ).format(
            pnt=pointShp, lnh=lineShp, out=outPoints,
            mv="" if not movesShp else " -MOVES {}".format(movesShp)
        )
        
        outcmd = exec_cmd(cmd)
    
    else:
        raise ValueError("{} is not available!".format(api))
    
    return outPoints
示例#24
0
文件: tplgy.py 项目: zonakre/gasp
def break_lines_on_points(lineShp, pointShp, lineIdInPntShp,
                         splitedShp, srsEpsgCode):
    """
    Break lines on points location
    
    The points should be contained by the lines;
    The points table should have a column with the id of the
    line that contains the point.
    """
    
    from shapely.ops      import split
    from shapely.geometry import Point, LineString
    from gasp.fm          import tbl_to_obj
    from gasp.mng.df      import col_list_val_to_row
    from gasp.to.obj      import dict_to_df
    from gasp.to.shp      import df_to_shp
    
    # Sanitize line geometry
    def fix_line(line, point):
        buff = point.buffer(0.0001)
        
        splitLine = split(line, buff)
        
        nline = LineString(
            list(splitLine[0].coords) + list(point.coords) +
            list(splitLine[-1].coords)
        )
        
        return nline
    
    pnts  = tbl_to_obj(pointShp, fields='ALL', output='array')
    lines = tbl_to_obj(lineShp, fields='ALL', output='dict')
    
    for point in pnts:
        rel_line = lines[point[lineIdInPntShp]]
        
        if type(rel_line["GEOM"]) != list:
            line_geom = fix_line(rel_line["GEOM"], point["GEOM"])
            
            split_lines = split(line_geom, point["GEOM"])
            
            lines[point[lineIdInPntShp]]["GEOM"] = [l for l in split_lines]
        
        else:
            for i in range(len(rel_line["GEOM"])):
                if rel_line["GEOM"][i].distance(point["GEOM"]) < 1e-8:
                    line_geom = fix_line(rel_line["GEOM"][i], point["GEOM"])
                    split_lines = split(line_geom, point["GEOM"])
                    split_lines = [l for l in split_lines]
                    
                    lines[point[lineIdInPntShp]]["GEOM"][i] = split_lines[0]
                    lines[point[lineIdInPntShp]]["GEOM"] += split_lines[1:]
                    
                    break
                
                else:
                    continue
    
    # Result to Dataframe
    linesDf = dict_to_df(lines)
    
    # Where GEOM is a List, create a new row for each element in list
    linesDf = col_list_val_to_row(
        linesDf, "GEOM", geomCol="GEOM", epsg=srsEpsgCode
    )
    
    # Save result
    return df_to_shp(linesDf, splitedShp)
示例#25
0
文件: geocode.py 项目: zonakre/gasp
def address_from_featcls(inShp, outShp, epsg_in):
    """
    Read a point geometry and return a table with the addresses
    """
    
    from gasp.web.glg.geocod import get_address
    from gasp.fm             import tbl_to_obj
    from gasp.to.geom        import regulardf_to_geodf
    from gasp.fm.geom        import pointxy_to_cols
    from gasp.prop.feat      import get_geom_type
    from gasp.to.obj         import df_to_dict, dict_to_df
    from gasp.to.shp         import df_to_shp
    
    # Convert ESRI Shapefile to GeoDataFrame
    geoDf = tbl_to_obj(inShp)
    
    # Get Geometry field name
    for col in geoDf.columns.values:
        if col == 'geom' or col ==  'geometry':
            F_GEOM = col
            break
        else:
            continue
    
    # Check if inShp has a Geom of Type Point
    inGeomType = get_geom_type(geoDf, geomCol=F_GEOM, gisApi='pandas')
    
    if inGeomType != 'Point' and inGeomType != 'MultiPoint':
        raise ValueError('The input geometry must be of type point')
    
    # Reproject geodf if necessary
    if epsg_in != 4326:
        from gasp.mng.prj import project
        
        geoDf = project(geoDf, None, 4326, gisApi='pandas')
    
    # Get Coords of each point
    geoDf = pointxy_to_cols(geoDf, F_GEOM, colX="x", colY='y')
    
    # Search for addresses
    geoDict = df_to_dict(geoDf)
    for idx in geoDict:
        glg_response = get_address(geoDict[idx]["y"], geoDict[idx]["x"])
        
        geoDict[idx]["G_ADDRESS"] = glg_response[0]['formatted_address']
        
        for i in glg_response[0]["address_components"]:
            if   i["types"][0] == 'street_mumber' : F = "G_PORT"
            elif i["types"][0] == 'route'         : F = "G_STREET"
            elif i["types"][0] == 'postal_code'   : F = "G_ZIPCODE"
            else: continue
            
            geoDict[idx][F] = i["long_name"]
    
    # Save results in a new file
    geoDf = dict_to_df(geoDict)
    geoDf = regulardf_to_geodf(geoDf, F_GEOM, 4326)
    
    geoDf.drop(["x", "y"], axis=1, inplace=True)
    
    if epsg_in != 4326:
        geoDf = project(geoDf, None, epsg_in, gisApi='pandas')
    
    df_to_shp(geoDf, outShp)
    
    return geoDf
示例#26
0
文件: count.py 项目: zonakre/gasp
def count_rows_by_entity_and_shpJoin(conPSQL, PG_TABLE, PG_ENTITY, PG_PIVOT_COL,
                                     SHP_TABLE, SHP_ENTITY, RESULT_SHP,
                                     WHERE=None):
    """
    Select and GROUP BY attrs generating a table as:

    ENTITY | ATTR_N | COUNT
       1   | 12ECIR |   X
       2   | 12ECIR |   X
       1   | 15ECIR |   X
       2   | 15ECIR |   X

    Then convert this table to the following
    ENTITY | 12ECIR | 15ECIR
       1   |   X    |   X
       2   |   X    |   X
    
    The last table will be joined with a given Shapefile
    
    TODO: See if PGSQL crosstab works to solve this problem
    """
    
    from gasp.to.obj      import series_to_list
    from gasp.mng.joins   import combine_dfs
    from gasp.fm.sql      import query_to_df
    from gasp.fm          import tbl_to_obj
    from gasp.sql.mng.tbl import del_tables
    from gasp.sql.mng.qw  import ntbl_by_query
    from gasp.to.shp      import df_to_shp
    
    # Get GROUP BYed data
    # Get row counting using GROUPBY with ENTITY AND PIVOT_COL
    q = ("SELECT {entity}, {pivc}, COUNT({entity}) AS n{entity} "
         "FROM {tbl} {whr}GROUP BY {entity}, {pivc}").format(
        entity=PG_ENTITY, tbl=PG_TABLE, pivc=PG_PIVOT_COL,
        whr="" if not WHERE else "WHERE {} ".format(WHERE)
    )
    
    selData = ntbl_by_query(conPSQL, "seldata", q, api='psql')
    
    # Get columns of the output table
    pivotCols = query_to_df(conPSQL,
        "SELECT {piv} FROM {tb} GROUP BY {piv}".format(
            tb=selData, piv=PG_PIVOT_COL
        ), db_api='psql'
    )
    pivotCols = series_to_list(pivotCols[PG_PIVOT_COL])
    
    # Get data for each new column - new column data in one dataframe
    pre_pivot = [query_to_df(conPSQL,
        "SELECT {entity}, n{entity} FROM {t} WHERE {c}='{pivcol}'".format(
            entity=PG_ENTITY, t=selData, c=PG_PIVOT_COL, pivcol=col
        ), db_api='psql'
    ) for col in pivotCols]
    
    # In pre_pivot DF, give the correct name to the n{entity} column
    for i in range(len(pre_pivot)):
        pre_pivot[i].rename(columns={
            "n{}".format(PG_ENTITY) : pivotCols[i]
        }, inplace=True)
    
    # Join all dataframes into one
    pivot_df = pre_pivot[0]
    pivot_df = combine_dfs(pivot_df, pre_pivot[1:], PG_ENTITY)
    
    # Join pivot_df to the Given ESRI Shapefile
    shpDf = tbl_to_obj(SHP_TABLE)
    
    shpDf = shpDf.merge(pivot_df, how='outer',
                        left_on=SHP_ENTITY, right_on=PG_ENTITY)
    
    df_to_shp(shpDf, RESULT_SHP)
    
    del_tables(conPSQL, selData)
    
    return RESULT_SHP
示例#27
0
def join_attr_by_distance(mainTable, joinTable, workGrass, epsg_code,
                          output):
    """
    Find nearest feature and join attributes of the nearest feature
    to the mainTable
    
    Uses GRASS GIS to find near lines.
    """
    
    import os
    from gasp.session import run_grass
    from gasp.fm      import tbl_to_obj
    from gasp.to.geom import regulardf_to_geodf
    from gasp.to.shp  import df_to_shp
    from gasp.oss     import get_filename
    
    # Create GRASS GIS Location
    grassBase = run_grass(workGrass, location='join_loc', srs=epsg_code)
    
    import grass.script as grass
    import grass.script.setup as gsetup
    gsetup.init(grassBase, workGrass, 'join_loc', 'PERMANENT')
    
    # Import some GRASS GIS tools
    from gasp.anls.prox        import grs_near as near
    from gasp.cpu.grs.mng.feat import geomattr_to_db
    from gasp.to.shp.grs       import shp_to_grs, grs_to_shp
    
    # Import data into GRASS GIS
    grsMain = shp_to_grs(mainTable, get_filename(
        mainTable, forceLower=True)
    ); grsJoin = shp_to_grs(joinTable, get_filename(
        joinTable, forceLower=True)
    )
    
    # Get distance from each feature of mainTable to the nearest feature
    # of the join table
    near(grsMain, grsJoin, nearCatCol="tocat", nearDistCol="todistance")
    
    # Export data from GRASS GIS
    ogrMain = grs_to_shp(grsMain, os.path.join(
        workGrass, 'join_loc', grsMain + '_grs.shp'), None, asMultiPart=True
    ); ogrJoin = grs_to_shp(grsJoin, os.path.join(
        workGrass, 'join_loc', grsJoin + '_grs.shp'), None, asMultiPart=True)
    
    dfMain = tbl_to_obj(ogrMain)
    dfJoin = tbl_to_obj(ogrJoin)
    
    dfResult = dfMain.merge(dfJoin, how='inner',
                            left_on='tocat', right_on='cat')
    
    dfResult.drop(["geometry_y", "cat_y"], axis=1, inplace=True)
    dfResult.rename(columns={"cat_x" : "cat_grass"}, inplace=True)
    
    dfResult["tocat"]     = dfResult["tocat"] - 1
    dfResult["cat_grass"] = dfResult["cat_grass"] - 1
    
    dfResult = regulardf_to_geodf(dfResult, "geometry_x", epsg_code)
    
    df_to_shp(dfResult, output)
    
    return output
示例#28
0
文件: geocode.py 项目: zonakre/gasp
def shp_from_address(inTbl, idAddr, addrCol, outShp,
                     epsg_out=4326, sheet_name=None,
                     doorNumber=None, zip4=None, zip3=None,
                     city=None, language=None, useComponents=None,
                     country=None):
    """
    Receive a table with a list of addresses and use the Google Maps API
    to get their position
    
    Preferred Address Structure:
    Rua+dos+Combatentes+da+Grande+Guerra,+14,+3030-185,+Coimbra
    
    Table Structure:
    idAddr | addrCol | doorNumber | zip4 | zip3 | city
    idAddr field and address field are demandatory
    
    For now, The input table must be a excel file or a dbf table
    
    # TODO: Some of the rows could not have Geometry
    """
    
    from gasp.web.glg.geocod import get_position
    from gasp.fm             import tbl_to_obj
    from gasp.to.geom        import pnt_dfwxy_to_geodf
    from gasp.oss            import get_fileformat
    from gasp.mng.fld.df     import fld_types
    from gasp.to.obj         import df_to_dict, dict_to_df
    from gasp.to.shp         import df_to_shp
    
    # Get Addresses
    tblFormat = get_fileformat(inTbl)
    
    tblAdr = tbl_to_obj(inTbl, sheet=sheet_name)
    
    # Check if given columns are in table
    fields = [idAddr, addrCol, doorNumber, zip4, zip3, city]
    for f in fields:
        if f:
            if f not in tblAdr.columns.values:
                raise ValueError("{} column not in {}".format(f, inTbl))
    
    # Convert numeric fields to unicode
    colTypes = fld_types(tblAdr)
    for col in colTypes:
        if colTypes[col] != 'object':
            if colTypes[col] == 'float32' or colTypes[col] == 'float64':
                tblAdr[col] = tblAdr[col].astype(int)
            
        tblAdr[col] = tblAdr[col].astype(unicode, 'utf-8')
    
    # Create search field
    if not useComponents:
        if doorNumber and zip4 and zip3 and city:
            tblAdr["search"] = tblAdr[addrCol] + unicode(",", "utf-8") + \
                tblAdr[doorNumber].astype(unicode, "utf-8") + unicode(",", "utf-8") + \
                tblAdr[zip4] + unicode("-", "utf-8") + \
                tblAdr[zip3] + unicode(",", "utf-8") + tblAdr[city]
    
        elif not doorNumber and zip4 and zip3 and city:
            tblAdr["search"] = tblAdr[addrCol] + unicode(",", "utf-8") + \
                tblAdr[zip4] + unicode("-", "utf-8") + \
                tblAdr[zip3] + unicode(",", "utf-8") + tblAdr[city]
    
        elif doorNumber and not zip4 and not zip3 and not city:
            tblAdr["search"] = tblAdr[addrCol] + unicode(",", "utf-8") + \
                tblAdr[doorNumber]
    
        elif not doorNumber and not zip4 and not zip3 and not city:
            tblAdr["search"] = tblAdr[addrCol]
    
        elif doorNumber and zip4 and not zip3 and city:
            tblAdr = tblAdr[addrCol] + unicode(",", "utf-8") + \
                tblAdr[doorNumber] + unicode(",", "utf-8") + \
                tblAdr[zip4] + unicode(",", "utf-8") + tblAdr[city]
    
        elif doorNumber and not zip4 and not zip3 and city:
            tblAdr["search"] = tblAdr[addrCol] + unicode(",", "utf-8") + \
                tblAdr[doorNumber] + unicode(",", "utf-8") + tblAdr[city]
    
        elif not doorNumber and zip4 and not zip3 and city:
            tblAdr["search"] = tblAdr[addrCol] + unicode(",", "utf-8") + \
                tblAdr[city]
    
        elif not doorNumber and zip4 and zip3 and not city:
            tblAdr["search"] = tblAdr[addrCol] + unicode(",", "utf-8") + \
                tblAdr[zip4] + unicode("-", "utf-8") + tblAdr[zip3]
    
        elif doorNumber and zip4 and not zip3 and not city:
            tblAdr["search"] = tblAdr[addrCol] + unicode(",", "utf-8") + \
                tblAdr[doorNumber] + unicode(",", "utf-8") + tblAdr[zip4]
    
        elif doorNumber and zip4 and zip3 and not city:
            tblAdr["search"] = tblAdr[addrCol] + unicode(",", "utf-8") + \
                tblAdr[doorNumber] + unicode(",", "utf-8") + tblAdr[zip4] + \
                unicode("-", "utf-8") + tblAdr[zip3]
    
        elif not doorNumber and zip4 and not zip3 and not city:
            tblAdr["search"] = tblAdr[addrCol] + unicode(",", "utf-8") + \
                tblAdr[zip4]
    
        elif not doorNumber and not zip4 and not zip3 and city:
            tblAdr["search"] = tblAdr[addrCol] + unicode(",", "utf-8") + \
                tblAdr[city]
    
        else:
            raise ValueError('Parameters are not valid')
    
        # Sanitize search string
        tblAdr["search"] = tblAdr.search.str.replace(' ', '+')
    tblAdr = df_to_dict(tblAdr)
    
    # Geocode Addresses
    for idx in tblAdr:
        if not useComponents:
            glg_response = get_position(
                tblAdr[idx]["search"], country=None,
                language=None, locality=None, postal_code=None
            )
        else:
            if zip4 and zip3:
                _postal = u'{}-{}'.format(tblAdr[idx][zip4], tblAdr[idx][zip3])
            
            elif zip4 and not zip3:
                _postal = u'{}'.format(tblAdr[idx][zip4])
            
            else:
                _postal = None
            
            glg_response = get_position(
                u"{}{}".format(
                    tblAdr[idx][addrCol], u",{}".format(
                        tblAdr[idx][doorNumber]
                    ) if doorNumber else u""
                ),
                country=country, language=language,
                locality=tblAdr[idx][city].replace(" ", "+") if city else None,
                postal_code=_postal.replace(" ", "+")
            )
        
        if not glg_response: continue
        
        tblAdr[idx]["x"] = glg_response[0]['geometry']['location']['lng']
        tblAdr[idx]["y"] = glg_response[0]['geometry']['location']['lat']
        
        tblAdr[idx]["G_ADRS"] = glg_response[0]["formatted_address"]
        
        for i in glg_response[0]["address_components"]:
            if   i["types"][0] == 'street_number' : F = "G_PORT"
            elif i["types"][0] == 'route'         : F = "G_STREET"
            elif i["types"][0] == 'postal_code'   : F = "G_ZIPCODE"
            else: continue
            
            tblAdr[idx][F] = i["long_name"]
    
    # Convert Dataframe to GeoDataframe
    geoAdr = pnt_dfwxy_to_geodf(dict_to_df(tblAdr), "x", "y", 4326)
    
    # Reproject if user wants it
    if epsg_out != 4326:
        from gasp.mng.prj import project
        geoAdr = project(geoAdr, None, epsg_out, gisApi='pandas')
    
    # To Shapefile
    df_to_shp(geoAdr, outShp)
    
    return geoAdr
示例#29
0
def joinLines_by_spatial_rel_raster(mainLines, mainId, joinLines,
                                    joinCol, outfile, epsg):
    """
    Join Attributes based on a spatial overlap.
    An raster based approach
    """
    
    import os;          import pandas
    from geopandas      import GeoDataFrame
    from gasp.to.geom   import regulardf_to_geodf
    from gasp.session   import run_grass
    from gasp.oss       import get_filename
    from gasp.oss.ops   import create_folder
    from gasp.mng.ext   import shpextent_to_boundary
    from gasp.mng.joins import join_dfs
    from gasp.mng.df    import df_groupBy
    from gasp.to.rst    import shp_to_raster
    from gasp.fm        import tbl_to_obj
    from gasp.to.shp    import df_to_shp
    
    workspace = create_folder(os.path.join(
        os.path.dirname(mainLines, 'tmp_dt')
    ))
    
    # Create boundary file
    boundary = shpextent_to_boundary(
        mainLines, os.path.join(workspace, "bound.shp"),
        epsg
    )
    
    boundRst = shp_to_raster(boundary, None, 5, -99, os.path.join(
        workspace, "rst_base.tif"), epsg=epsg, api='gdal')
    
    # Start GRASS GIS Session
    gbase = run_grass(workspace, location="grs_loc", srs=boundRst)
    
    import grass.script       as grass
    import grass.script.setup as gsetup
    
    gsetup.init(gbase, workspace, "grs_loc", "PERMANENT")
    
    from gasp.spanlst.local   import combine
    from gasp.cpu.grs.spanlst import get_rst_report_data
    from gasp.to.shp.grs      import shp_to_grs, grs_to_shp
    from gasp.to.rst          import shp_to_raster
    
    # Add data to GRASS GIS
    mainVector = shp_to_grs(
        mainLines, get_filename(mainLines, forceLower=True))
    joinVector = shp_to_grs(
        joinLines, get_filename(joinLines, forceLower=True))
    
    mainRst = shp_to_raster(
        mainVector, mainId, None, None, "rst_" + mainVector, api='pygrass'
    ); joinRst = shp_to_raster(
        joinVector, joinCol, None, None, "rst_" + joinVector, api='pygrass'
    )
    
    combRst = combine(mainRst, joinRst, "combine_rst", api="pygrass")
    
    combine_data = get_rst_report_data(combRst, UNITS="c")
    
    combDf = pandas.DataFrame(combine_data, columns=[
        "comb_cat", "rst_1", "rst_2", "ncells"
    ])
    combDf = combDf[combDf["rst_2"] != '0']
    combDf["ncells"] = combDf["ncells"].astype(int)
    
    gbdata = df_groupBy(combDf, ["rst_1"], "MAX", "ncells")
    
    fTable = join_dfs(gbdata, combDf, ["rst_1", "ncells"], ["rst_1", "ncells"])
    
    fTable["rst_2"] = fTable["rst_2"].astype(int)
    fTable = df_groupBy(
        fTable, ["rst_1", "ncells"],
        STAT='MIN', STAT_FIELD="rst_2"
    )
    
    mainLinesCat = grs_to_shp(
        mainVector, os.path.join(workspace, mainVector + '.shp'), 'line')
    
    mainLinesDf = tbl_to_obj(mainLinesCat)
    
    resultDf = join_dfs(
        mainLinesDf, fTable, "cat", "rst_1",
        onlyCombinations=None
    )
    
    resultDf.rename(columns={"rst_2" : joinCol}, inplace=True)
    
    resultDf = regulardf_to_geodf(resultDf, "geometry", epsg)
    
    df_to_shp(resultDf, outfile)
    
    return outfile
示例#30
0
文件: dmx.py 项目: zonakre/gasp
def pnt_to_facility(pnt, pntSrs, facilities, facSrs, transMode="driving"):
    """
    Calculate distance between points and the nearest facility.
    
    # TODO: Add the possibility to save the path between origins and
    destinations
    """

    import os
    import time
    from gasp.fm import tbl_to_obj
    from gasp.to.geom import regulardf_to_geodf
    from gasp.mng.prj import project_df
    from gasp.prop.feat import get_geom_type
    from gasp.oss import get_filename
    from gasp.to.obj import df_to_dict, dict_to_df
    from gasp.to.shp import df_to_shp
    from gasp.web.glg.distmx import dist_matrix

    # Convert SHPs to GeoDataFrame
    pntDf = tbl_to_obj(pnt)
    tbl_to_obj(facilities)

    # Check if SHPs are points
    originsGeom = get_geom_type(pntDf, geomCol="geometry", gisApi='pandas')
    if originsGeom != 'Point' and originsGeom != 'MultiPoint':
        raise ValueError('All input geometry must be of type point')

    destGeom = get_geom_type(facil, geomCol="geometry", gisApi='pandas')
    if destGeom != 'Point' and destGeom != 'MultiPoint':
        raise ValueError('All input geometry must be of type point')

    # Re-Project if necessary
    pntDf = pntDf if pntSrs == 4326 else project(
        pntDf, None, 4326, gisApi='pandas')
    facil = facil if facSrs == 4326 else project(
        facil, None, 4326, gisApi='pandas')

    # Coords to cols as str
    pntDf["geom"] = pntDf["geometry"].y.astype(str) + "," + \
        pntDf["geometry"].x.astype(str)

    facil["geom"] = facil["geometry"].y.astype(str) + "," + \
        facil["geometry"].y.astype(str)

    # Get distance between points and nearest facility
    pntDict = df_to_dict(pntDf)

    for idx in pntDict:
        destStr = str(facil["geom"].str.cat(sep="|"))

        glg_resp = dist_matrix(pntDict[idx]["geom"],
                               destStr,
                               1,
                               int(facil.shape[0]),
                               transport_mode=transMode)

        matrix = pandas.DataFrame(glg_resp[0]["elements"])

        matrix.drop(["status", "distance"], axis=1, inplace=True)
        matrix = pandas.concat([
            matrix.drop(["duration"], axis=1), matrix["duration"].apply(
                pandas.Series)
        ],
                               axis=1)

        matrix.drop("text", axis=1, inplace=True)
        matrix.rename(columns={"value": "duration"}, inplace=True)

        pntDict[idx]["duration"] = matrix.duration.min() / 60.0

    pntDf = dict_to_df(pntDict)
    pntDf = regulardf_to_geodf(pntDf, "geometry", 4326)

    if pntSrs != 4326:
        pntDf = project(pntDf, None, pntSrs, gisApi='pandas')

    df_to_shp(
        pntDf,
        os.path.join(os.path.dirname(pnt),
                     "{}_{}.shp".format(get_filename(pnt), "result")))

    return pntDf