Example #1
0
def gdb_to_shp(workspace, outworkspace):
    """
    Export all feature classes in a Geodatabase to a single file.
    Do this for all Geodatabases in workspace.
    """

    import os
    from glass.mng.gen import copy_feat

    # List GeoDatabases
    lst_gdb = arcpy.ListWorkspaces(workspace_type="FileGDB")

    dic_gdb = {}

    for gdb in lst_gdb:
        arcpy.env.workspace = gdb

        dic_gdb[gdb] = {}

        dts = arcpy.ListDatasets()

        for dt in dts:
            dic_gdb[gdb][dt] = arcpy.ListFeatureClasses(feature_dataset=dt)

    for gdb in dic_gdb:
        for dt in dic_gdb[gdb]:
            for fc in dic_gdb[gdb][dt]:
                copy_feat(os.path.join(gdb, dt, fc),
                          os.path.join(
                              outworkspace, "{}_{}.shp".format(
                                  os.path.splitext(os.path.basename(gdb))[0],
                                  fc)),
                          gisApi='arcpy')
Example #2
0
def round_table_values(table, decimal_by_col_file, outputFile):
    """
    Round all column values using the number of decimal places written
    in a excel file
    
    COL_NAME | nr_decimal_places
    COL_1    | 1
    COL_2    | 0
    ...      | ...
    COL_N    | 2
    """
    
    from glass.cpu.arcg.lyr     import feat_lyr
    from glass.mng.gen          import copy_feat
    from glass.cpu.arcg.mng.fld import type_fields
    from glass.fm               import tbl_to_obj
    
    arcpy.env.overwriteOutput = True
    
    # Get number of decimal places for the values of each column
    places_by_col = tbl_to_obj(
        decimal_by_col_file, sheet=0, output='dict', useFirstColAsIndex=True
    )
    
    PLACES_FIELD = places_by_col[places_by_col.keys()[0]].keys()[0]
    
    # Copy table
    outTable = copy_feat(table, outputFile, gisApi='arcpy')
    
    # Edit copy putting the correct decimal places in each column
    lyr = feat_lyr(outTable)
    
    # List table fields
    fields = type_fields(lyr)
    cursor = arcpy.UpdateCursor(lyr)
    for lnh in cursor:
        for col in fields:
            if col in places_by_col:
                if fields[col] == 'Integer' or fields[col] == 'Double' \
                   or fields[col] == 'SmallInteger':
                    value = lnh.getValue(col)
                
                    lnh.setValue(
                        col, 
                        round(value, int(places_by_col[col][PLACES_FIELD]))
                    )
                else:
                    continue
            else:
                print("{} not in {}".format(col, decimal_by_col_file))
        
        cursor.updateRow(lnh)
    
    del lyr
    
    return outputFile
Example #3
0
def mean_rst_by_polygon(polygons, raster, work, resultShp):
    """
    Mean of all cells intersect with the input polygon features
    """

    import arcpy
    import os

    from glass.cpu.arcg.lyr import feat_lyr, rst_lyr
    from glass.prop.rst import rst_stats
    from glass.cpu.arcg.mng.fld import add_field
    from glass.mng.gen import copy_feat
    from glass.cpu.arcg.anls.exct import select_by_attr
    from glass.cpu.arcg.mng.rst.proc import clip_raster

    # ########### #
    # Environment #
    # ########### #
    arcpy.env.overwriteOutput = True
    arcpy.env.workspace = work

    # ###### #
    # Do it! #
    # ###### #
    # Copy the Input
    poly_copy = copy_feat(polygons, resultShp, gisApi='arcpy')
    # Create Layers
    lyrShp = feat_lyr(poly_copy)
    lyrRst = rst_lyr(raster)
    # Create field for register calculated statistics
    if len(os.path.basename(raster)) <= 10:
        fld_name = os.path.basename(raster)
    else:
        fld_name = os.path.basename(raster)[:10]
    add_field(lyrShp, fld_name, "DOUBLE", "20", "3")
    # Calculate mean
    c = arcpy.UpdateCursor(lyrShp)
    l = c.next()
    while l:
        fid = str(l.getValue("FID"))
        selection = select_by_attr(lyrShp, "FID={c}".format(c=fid),
                                   "poly_{c}.shp".format(c=fid))
        sel_rst = clip_raster(lyrRst, selection,
                              "clip_rst_{c}.img".format(c=fid))

        mean = rst_stats(sel_rst, api='arcpy')["MEAN"]
        l.setValue(fld_name, mean)
        c.updateRow(l)
        l = c.next()
Example #4
0
def arcg_mean_time_WByPop2(netDt,
                           rdv,
                           infraestruturas,
                           unidades,
                           conjuntos,
                           popf,
                           w,
                           output,
                           oneway=None):
    """
    Tempo medio ponderado pela populacao residente a infra-estrutura mais
    proxima (min)
    
    * netDt = Path to Network Dataset
    * infraestruturas = Points of destiny
    * unidades = BGRI; Freg; Concelhos
    * conjuntos = Freg; Concelhos; NUT - field
    * popf = Field with the population of the statistic unity
    * w = Workspace
    * output = Path to store the final output
    * rdv = Name of feature class with the streets network
    """

    import arcpy
    import os
    from glass.cpu.arcg.lyr import feat_lyr
    from glass.cpu.arcg.mng.feat import feat_to_pnt
    from glass.cpu.arcg.mng.fld import add_field, calc_fld
    from glass.cpu.arcg.mng.joins import join_table
    from glass.mng.genze import dissolve
    from glass.mng.gen import copy_feat
    from glass.mob.arctbx.closest import closest_facility
    from glass.dct import tbl_to_obj

    def get_freg_denominator(shp, groups, population, fld_time="Total_Minu"):
        cursor = arcpy.SearchCursor(shp)

        groups_sum = {}
        for lnh in cursor:
            group = lnh.getValue(groups)
            nrInd = float(lnh.getValue(population))
            time = float(lnh.getValue(fld_time))

            if group not in groups_sum.keys():
                groups_sum[group] = time * nrInd

            else:
                groups_sum[group] += time * nrInd

        del cursor, lnh

        return groups_sum

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

    arcpy.env.overwriteOutput = True
    arcpy.env.workspace = w

    # Start Procedure #
    # Create copy of statitic unities to preserve the original data
    copy_unities = copy_feat(unidades,
                             os.path.join(w, os.path.basename(unidades)),
                             gisApi='arcpy')

    # Generate centroids of the statistic unities - unidades
    lyr_unidades = feat_lyr(copy_unities)
    pnt_unidades = feat_to_pnt(lyr_unidades, 'pnt_unidades.shp')

    # Network Processing - Distance between CENTROID and Destiny points
    closest_facility(netDt,
                     rdv,
                     infraestruturas,
                     pnt_unidades,
                     os.path.join(w, "cls_table.dbf"),
                     oneway_restriction=oneway)
    add_field("cls_table.dbf", 'j', "SHORT", "6")
    calc_fld("cls_table.dbf", 'j', "[IncidentID]-1")
    join_table(lyr_unidades, "FID", "cls_table.dbf", "j", "Total_Minu")
    del lyr_unidades

    # Calculo dos somatorios por freguesia (conjunto)
    # To GeoDf
    unidadesDf = tbl_to_obj(copy_unities)
    """
    groups = get_freg_denominator(lyr_unidades, conjuntos, popf)
    add_field(lyr_unidades, "tm", "FLOAT", "10", "3")
    
    cs = arcpy.UpdateCursor(lyr_unidades)
    linha = cs.next()
    while linha:
        group = linha.getValue(conjuntos)
        t = float(linha.getValue("Total_Minu"))
        p = int(linha.getValue(popf))
        total = groups[group]
        indi = ((t * p) / total) * t
        linha.setValue("tm", indi)
        cs.updateRow(linha)
        linha = cs.next()
    
    return dissolve(lyr_unidades, output, conjuntos, "tm SUM")"""
    return unidadesDf
Example #5
0
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 glass.cpu.arcg.lyr import feat_lyr
    from glass.cpu.arcg.anls.ovlay import intersect
    from glass.mng.gen import copy_feat
    from glass.cpu.arcg.mng.fld import add_geom_attr
    from glass.cpu.arcg.mng.fld import add_field
    from glass.cpu.arcg.mng.fld import calc_fld
    from glass.mng.genze import dissolve
    from glass.mob.arctbx.svarea import service_area_use_meters
    from glass.mob.arctbx.svarea import service_area_polygon
    from glass.fm import tbl_to_obj
    from glass.toshp import df_to_shp

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

    if not os.path.exists(workspace):
        from glass.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
Example #6
0
def mean_time_in_povoated_areas(network,
                                rdv_name,
                                stat_units,
                                popFld,
                                destinations,
                                output,
                                workspace,
                                ONEWAY=True,
                                GRID_REF_CELLSIZE=10):
    """
    Receive statistical units and some destinations. Estimates the mean distance
    to that destinations for each statistical unit.
    The mean for each statistical will be calculated using a point grid:
    -> Statistical unit to grid point;
    -> Distance from grid point to destination;
    -> Mean of these distances.
    
    This method will only do the math for areas (statistic units)
    with population.
    """

    import os
    import arcpy
    from glass.cpu.arcg.lyr import feat_lyr
    from glass.cpu.arcg.anls.exct import select_by_attr
    from glass.cpu.arcg.mng.fld import field_statistics
    from glass.cpu.arcg.mng.fld import add_field
    from glass.cpu.arcg.mng.gen import merge
    from glass.mng.gen import copy_feat
    from glass.mob.arctbx.closest import closest_facility
    from glass.to.shp.arcg import rst_to_pnt
    from glass.to.rst import shp_to_raster

    if arcpy.CheckExtension("Network") == "Available":
        arcpy.CheckOutExtension("Network")

    else:
        raise ValueError('Network analyst extension is not avaiable')

    arcpy.env.overwriteOutput = True

    WORK = workspace

    # Add field
    stat_units = copy_feat(stat_units,
                           os.path.join(WORK, os.path.basename(stat_units)),
                           gisApi='arcpy')
    add_field(stat_units, "TIME", "DOUBLE", "10", precision="3")

    # Split stat_units into two layers
    # One with population
    # One with no population
    withPop = select_by_attr(stat_units, '{}>0'.format(popFld),
                             os.path.join(WORK, 'with_pop.shp'))
    noPop = select_by_attr(stat_units, '{}=0'.format(popFld),
                           os.path.join(WORK, 'no_pop.shp'))

    # For each statistic unit with population
    withLyr = feat_lyr(withPop)
    cursor = arcpy.UpdateCursor(withLyr)

    FID = 0
    for feature in cursor:
        # Create a new file
        unity = select_by_attr(
            withLyr, 'FID = {}'.format(str(FID)),
            os.path.join(WORK, 'unit_{}.shp'.format(str(FID))))

        # Convert to raster
        rst_unity = shp_to_raster(unity,
                                  "FID",
                                  GRID_REF_CELLSIZE,
                                  None,
                                  os.path.join(WORK,
                                               'unit_{}.tif'.format(str(FID))),
                                  api='arcpy')

        # Convert to point
        pnt_unity = rst_to_pnt(
            rst_unity, os.path.join(WORK, 'pnt_un_{}.shp'.format(str(FID))))

        # Execute closest facilitie
        CLOSEST_TABLE = os.path.join(WORK, 'cls_fac_{}.dbf'.format(str(FID)))
        closest_facility(network,
                         rdv_name,
                         destinations,
                         pnt_unity,
                         CLOSEST_TABLE,
                         oneway_restriction=ONEWAY)

        # Get Mean
        MEAN_TIME = field_statistics(CLOSEST_TABLE, 'Total_Minu', 'MEAN')[0]

        # Record Mean
        feature.setValue("TIME", MEAN_TIME)
        cursor.updateRow(feature)

        FID += 1

    merge([withPop, noPop], output)

    return output
Example #7
0
def mean_time_by_influence_area(netDt,
                                rdv,
                                infraestruturas,
                                fld_infraestruturas,
                                unidades,
                                id_unidade,
                                conjuntos,
                                popf,
                                influence_areas_unities,
                                w,
                                output,
                                oneway=True):
    """
    Tempo medio ponderado pela populacao residente a infra-estrutura mais
    proxima (min), por area de influencia
    
    * netDt - Path to Network Dataset
    * infraestruturas - Points of destiny
    * fld_infraestruturas - Field on destiny points to relate with influence area
    * unidades - BGRI; Freg; Concelhos
    * conjuntos - Freg; Concelhos; NUT - field
    * popf - Field with the population of the statistic unity
    * influence_areas_unities - Field on statistic unities layer to relate
    with influence area
    * w = Workspace
    * output = Path to store the final output
    * rdv - Name of feature class with the streets network
    * junctions - Name of feature class with the junctions
    """

    import arcpy
    import os
    from glass.cpu.arcg.lyr import feat_lyr
    from glass.cpu.arcg.mng.feat import feat_to_pnt
    from glass.cpu.arcg.mng.gen import merge
    from glass.mng.gen import copy_feat
    from glass.mng.genze import dissolve
    from glass.cpu.arcg.mng.fld import add_field
    from glass.cpu.arcg.mng.fld import calc_fld
    from glass.cpu.arcg.mng.fld import field_statistics
    from glass.cpu.arcg.mng.fld import type_fields
    from glass.cpu.arcg.mng.joins import join_table
    from glass.cpu.arcg.anls.exct import select_by_attr
    from glass.cpu.arcg.netanlst.closest import closest_facility
    """if arcpy.CheckExtension("Network") == "Available":
        arcpy.CheckOutExtension("Network")
    
    else:
        raise ValueError('Network analyst extension is not avaiable')"""
    def ListGroupArea(lyr, fld_ia, fld_grp):
        d = {}
        cs = arcpy.SearchCursor(lyr)
        for lnh in cs:
            id_group = lnh.getValue(fld_grp)
            id_ia = lnh.getValue(fld_ia)
            if id_group not in d.keys():
                d[id_group] = [id_ia]
            else:
                if id_ia not in d[id_group]:
                    d[id_group].append(id_ia)
        return d

    arcpy.env.overwriteOutput = True
    arcpy.env.workspace = w

    # Procedure #
    copy_unities = copy_feat(unidades,
                             os.path.join(w, os.path.basename(unidades)),
                             gisApi='arcpy')

    # Generate centroids of the statistic unities - unidades
    lyr_unidades = feat_lyr(copy_unities)
    pnt_unidades = feat_to_pnt(lyr_unidades,
                               'pnt_unidades.shp',
                               pnt_position="INSIDE")
    # List all groups of unities (conjuntos)
    group_areas = ListGroupArea(lyr_unidades, influence_areas_unities,
                                conjuntos)
    # Create Layers
    lyr_pnt_unidades = feat_lyr(pnt_unidades)
    lyr_pnt_facilities = feat_lyr(infraestruturas)

    result_list = []

    fld_type_unities = type_fields(lyr_pnt_unidades, field=conjuntos)
    SELECT_UNITIES = '{fld}=\'{c}\'' if str(fld_type_unities) == 'String' \
        else '{fld}={c}'

    fld_type_facilities = type_fields(lyr_pnt_facilities,
                                      field=fld_infraestruturas)
    SELECT_FACILITIES = '{fld}=\'{obj}\'' if str(fld_type_facilities) == 'String' \
        else '{fld}={obj}'
    for group in group_areas.keys():
        # Select centroids of interest
        interest_centroids = select_by_attr(
            lyr_pnt_unidades, SELECT_UNITIES.format(c=str(group),
                                                    fld=conjuntos),
            'pnt_{c}.shp'.format(c=str(group)))
        # Select facilities of interest
        expression = ' OR '.join([
            SELECT_FACILITIES.format(fld=fld_infraestruturas,
                                     obj=str(group_areas[group][i]))
            for i in range(len(group_areas[group]))
        ])

        interest_facilities = select_by_attr(
            lyr_pnt_facilities, expression,
            'facilities_{c}.shp'.format(c=str(group)))
        # Run closest facilitie - Distance between selected CENTROID and selected facilities
        cls_fac_table = os.path.join(w, "clsf_{c}.dbf".format(c=str(group)))
        closest_facility(netDt,
                         rdv,
                         interest_facilities,
                         interest_centroids,
                         cls_fac_table,
                         oneway_restriction=oneway)
        add_field(cls_fac_table, 'j', "SHORT", "6")
        calc_fld(cls_fac_table, 'j', "[IncidentID]-1")
        join_table(interest_centroids, "FID", cls_fac_table, "j", "Total_Minu")
        # Calculate sum of time x population
        add_field(interest_centroids, 'sum', "DOUBLE", "10", "3")
        calc_fld(interest_centroids, 'sum',
                 "[{pop}]*[Total_Minu]".format(pop=popf))
        denominador = field_statistics(interest_centroids, 'sum', 'SUM')
        add_field(interest_centroids, 'tm', "DOUBLE", "10", "3")
        calc_fld(
            interest_centroids, 'tm',
            "([sum]/{sumatorio})*[Total_Minu]".format(
                sumatorio=str(denominador)))
        result_list.append(interest_centroids)

    merge_shp = merge(result_list, "merge_centroids.shp")
    join_table(lyr_unidades, id_unidade, "merge_centroids.shp", id_unidade,
               "tm")

    return dissolve(lyr_unidades,
                    output,
                    conjuntos,
                    statistics="tm SUM",
                    api='arcpy')
Example #8
0
def service_area_use_meters(net,
                            rdv,
                            distance,
                            loc,
                            out,
                            OVERLAP=True,
                            ONEWAY=None):
    """
    Execute service area tool using metric distances
    """

    from glass.mng.gen import copy_feat

    if arcpy.CheckExtension("Network") == "Available":
        arcpy.CheckOutExtension("Network")

    else:
        raise ValueError('Network analyst extension is not avaiable')

    network_name = str(os.path.basename(net))
    JUNCTIONS = network_name + '_Junctions'

    oneway = "" if not ONEWAY else "Oneway"

    INTERVALS = str(distance) if type(distance) == int or \
        type(distance) == float else distance if \
        type(distance) == str or type(distance) == unicode \
        else ' '.join([str(int(x)) for x in distance]) if \
        type(distance) == list else None

    if not INTERVALS: raise ValueError(('distance format is not valid'))

    arcpy.MakeServiceAreaLayer_na(
        in_network_dataset=net,
        out_network_analysis_layer="servArea",
        impedance_attribute="Length",
        travel_from_to="TRAVEL_FROM",
        default_break_values=INTERVALS,
        polygon_type="DETAILED_POLYS",
        merge="NO_MERGE" if OVERLAP else "NO_OVERLAP",
        nesting_type="RINGS",
        line_type="NO_LINES",
        overlap="OVERLAP" if OVERLAP else "NON_OVERLAP",
        split="NO_SPLIT",
        excluded_source_name="",
        accumulate_attribute_name="",
        UTurn_policy="NO_UTURNS",
        restriction_attribute_name=oneway,
        polygon_trim="TRIM_POLYS",
        poly_trim_value="250 Meters",
        lines_source_fields="NO_LINES_SOURCE_FIELDS",
        hierarchy="NO_HIERARCHY",
        time_of_day="")

    # Add locations to the service area layer
    arcpy.AddLocations_na(
        "servArea", "Facilities", loc, "", "5000 Meters", "",
        "{_rdv} SHAPE;{j} NONE".format(_rdv=str(rdv), j=str(JUNCTIONS)),
        "MATCH_TO_CLOSEST", "APPEND", "NO_SNAP", "5 Meters", "INCLUDE",
        "{_rdv} #;{j} #".format(_rdv=str(rdv), j=str(JUNCTIONS)))
    # Solve
    arcpy.Solve_na("servArea", "SKIP", "TERMINATE", "")
    # Export to a shapefile
    save_servArea = copy_feat("servArea\\Polygons", out, gisApi='arcpy')

    return save_servArea