Ejemplo n.º 1
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
Ejemplo n.º 2
0
def clip_each_feature(rst, shp, feature_id, work, out_basename):
    """
    Clip a raster dataset for each feature in a feature class
    """

    import arcpy
    import os

    from glass.cpu.arcg.lyr import feat_lyr
    from glass.cpu.arcg.lyr import rst_lyr
    from glass.cpu.arcg.anls.exct import select_by_attr
    from glass.oss.ops import create_folder

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

    # ###### #
    # Do it! #
    # ###### #
    # Open feature class
    lyr_shp = feat_lyr(shp)
    lyr_rst = rst_lyr(rst)

    # Create folder for some temporary files
    wTmp = create_folder(os.path.join(work, 'tmp'))

    # Get id's field type
    fields = arcpy.ListFields(lyr_shp)
    for f in fields:
        if str(f.name) == str(feature_id):
            fld_type = f.type
            break

    expression = '{fld}=\'{_id}\'' if str(fld_type) == 'String' else \
        '{fld}={_id}'

    del fields, f

    # Run the clip tool for each feature in the shp input
    c = arcpy.SearchCursor(lyr_shp)
    l = c.next()
    while l:
        fid = str(l.getValue(feature_id))
        selection = select_by_attr(
            lyr_shp, expression.format(fld=feature_id, _id=fid),
            os.path.join(wTmp, 'each_{}.shp'.format(fid)))

        clip_rst = clip_raster(lyr_rst, selection,
                               '{b}_{_id}.tif'.format(b=out_basename, _id=fid))

        l = c.next()
Ejemplo n.º 3
0
def TIN_nodata_interpolation(inRst,
                             boundary,
                             prj,
                             cellsize,
                             outRst,
                             workspace=None,
                             template=None):
    """
    Preenche os valores NoData de uma imagem raster usando um TIN
    """

    import os
    from glass.oss import get_filename
    from glass.cpu.arcg.lyr import rst_lyr
    from glass.cpu.arcg.lyr import feat_lyr
    from glass.cpu.to.shp.arcg import rst_to_pnt
    from glass.cpu.arcg._3D.mng.tin import create_tin
    from glass.cpu.to.rst.arcg import tin_to_raster

    workspace = workspace if workspace else \
        os.path.dirname(outRst)

    # Convert Input Raster to a Point Feature Class
    rstLyr = rst_lyr(inRst)
    pntRst = rst_to_pnt(
        rstLyr, os.path.join(workspace,
                             get_filename(inRstinRst) + '.shp'))

    # Create TIN
    pntrstLyr = feat_lyr(pntRst)
    lmtLyr = feat_lyr(boundary)

    tinInputs = ('{bound} <None> Soft_Clip <None>;'
                 '{rst_pnt} GRID_CODE Mass_Points <None>')

    tinOutput = os.path.join(workspace, 'tin_' + get_filename(inRst))

    create_tin(tinOutput, prj, tinInputs)

    return tin_to_raster(tinOutput, cellsize, outRst, template=template)
Ejemplo n.º 4
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()
Ejemplo n.º 5
0
def polygons_to_facility(netdataset,
                         polygons,
                         facilities,
                         outTbl,
                         oneway=None,
                         rdv=None,
                         junctions=None,
                         save_result_input=None):
    """
    Execute the Closest Facility tool after calculation of polygons
    centroids
    """

    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
    from glass.cpu.arcg.mng.fld import calc_fld
    from glass.cpu.arcg.mng.joins import join_table

    arcpy.env.overwriteOutput = True

    # Polygons to Points
    polLyr = feat_lyr(polygons)
    pntShp = os.path.join(
        os.path.dirname(polygons),
        os.path.splitext(os.path.basename(polygons))[0] + '_pnt.shp')
    pntShp = feat_to_pnt(polLyr, pntShp, pnt_position='INSIDE')

    closest_facility(netdataset,
                     facilities,
                     pntShp,
                     outTbl,
                     oneway_restriction=oneway,
                     rdv=rdv,
                     junc=junctions)

    field_output = 'dst' + os.path.splitext(os.path.basename(facilities))[0]
    add_field(outTbl, field_output[:10], "FLOAT", "10", "3")
    calc_fld(outTbl, field_output[:10], "[Total_Minu]")

    if save_result_input:
        add_field(outTbl, 'j', "SHORT", "6")
        calc_fld(outTbl, 'j', "[IncidentID]-1")
        join_table(polLyr, "FID", outTbl, "j", field_output[:10])
Ejemplo n.º 6
0
def polygons_from_points(inputPnt,
                         outputPol,
                         prj,
                         POLYGON_FIELD,
                         ORDER_FIELD=None):
    """
    Create a Polygon Table from a Point Table
    
    A given Point Table:
    FID | POLYGON_ID | ORDER_FIELD
     0  |    P1      |      1
     1  |    P1      |      2
     2  |    P1      |      3
     3  |    P1      |      4
     4  |    P2      |      1
     5  |    P2      |      2
     6  |    P2      |      3
     7  |    P2      |      4
     
    Will be converted into a new Polygon Table:
    FID | POLYGON_ID
     0  |    P1
     1  |    P2
     
    In the Point Table, the POLYGON_ID field identifies the Polygon of that point,
    the ORDER FIELD specifies the position (first point, second point, etc.)
    of the point in the polygon.
    
    If no ORDER field is specified, the points will be assigned to polygons
    by reading order.
    """

    import os
    from glass.cpu.arcg.lyr import feat_lyr
    from glass.cpu.arcg.mng.featcls import create_feat_class
    from glass.cpu.arcg.mng.fld import add_field
    from glass.cpu.arcg.mng.fld import type_fields

    arcpy.env.overwriteOutput = True

    # TODO: Check Geometry of the Inputs

    # List all point
    pntLyr = feat_lyr(inputPnt)
    cursor = arcpy.SearchCursor(pntLyr)
    line = cursor.next()

    lPnt = {}
    cnt = 0
    while line:
        # Get Point Geom
        pnt = line.Shape.centroid
        # Get Polygon Identification
        polygon = line.getValue(POLYGON_FIELD)
        # Get position in the polygon
        order = line.getValue(ORDER_FIELD) if ORDER_FIELD else cnt

        # Store data
        if polygon not in lPnt.keys():
            lPnt[polygon] = {order: (pnt.X, pnt.Y)}

        else:
            lPnt[polygon].update({order: (pnt.X, pnt.Y)})

        line = cursor.next()
        cnt += 1

    del line
    del cursor

    # Write Output
    create_feat_class(outputPol, "POLYGON", prj)

    outLyr = feat_lyr(outputPol)

    # Add polygon ID
    fieldsPnt = type_fields(pntLyr)

    POLYGON_FIELD_TYPE = "TEXT" if fieldsPnt[POLYGON_FIELD] == 'String' \
        else "SHORT" if fieldsPnt[POLYGON_FIELD] == 'Integer' else \
        "TEXT"
    POLYGON_FIELD_PRECISION = 50 if POLYGON_FIELD_TYPE == "TEXT" else \
        15

    add_field(outLyr, POLYGON_FIELD, POLYGON_FIELD_TYPE,
              POLYGON_FIELD_PRECISION)

    cursor = arcpy.InsertCursor(outLyr)

    # Add Polygons
    point = arcpy.CreateObject("Point")
    for polygon in lPnt:
        vector = arcpy.CreateObject("Array")

        pnt_order = lPnt[polygon].keys()
        pnt_order.sort()

        for p in pnt_order:
            point.ID = p
            point.X = lPnt[polygon][p][0]
            point.Y = lPnt[polygon][p][1]
            vector.add(point)

        # Add last point
        point.X = lPnt[polygon][pnt_order[0]][0]
        point.Y = lPnt[polygon][pnt_order[0]][1]
        vector.add(point)

        new_row = cursor.newRow()
        new_row.Shape = vector

        new_row.setValue(POLYGON_FIELD, str(polygon))

        cursor.insertRow(new_row)

        vector = 0
Ejemplo n.º 7
0
def service_area_as_sup_cst(networkDataset,
                            rdvName,
                            extentLyr,
                            originsLyr,
                            output,
                            epsg=3763,
                            REF_DISTANCE=3000,
                            NR_INTERVALS=20):
    """
    Create a Cost Distance Surface using Service Area Tool
    
    Same result of the Cost Distance tool but using Service Area Tool
    
    Supported by Google Maps API
    
    PROBLEM: REF_DISTANCE should be greater if the extent is higher.
    """

    import os

    from glass.prop.ext import get_extent
    from glass.cpu.arcg.lyr import feat_lyr
    from glass.to.shp.arcg import geomArray_to_fc
    from glass.mob.arctbx.svarea import service_area_polygon
    from glass.web.glg.distmatrix import get_max_dist

    if epsg != 4326:
        from glass.mng.prj import project

    arcpy.env.overwriteOutput = True

    # Get extent
    minX, maxX, minY, maxY = get_extent(extentLyr, gisApi='arcpy')

    # Get Reference points through the boundary
    # Get North West to East
    north_west_east = [(minX, maxY)]
    # Get South West to East
    south_west_east = [(minX, minY)]
    c = minX
    while c < maxX:
        north_west_east.append((c, maxY))
        south_west_east.append((c, minY))
        c += REF_DISTANCE

    north_west_east.append((maxX, maxY))
    south_west_east.append((maxX, minY))

    # Get West North to South
    west_north_to_south = [(minX, maxY)]
    # Get East North to South
    east_north_to_south = [(maxX, maxY)]
    c = maxY
    while c > minY:
        west_north_to_south.append((minX, c))
        east_north_to_south.append((maxX, c))
        c -= REF_DISTANCE

    west_north_to_south.append((minX, minY))
    east_north_to_south.append((maxX, minY))

    south_west_east.reverse()
    west_north_to_south.reverse()

    # Export Ref Points to a file only to see the result
    REF_GEOM = north_west_east + east_north_to_south + \
        south_west_east + west_north_to_south
    line_array = [{'FID': 0, "GEOM": REF_GEOM}]

    REF_POINTS = os.path.join(os.path.dirname(output), 'extent.shp')
    geomArray_to_fc(line_array, REF_POINTS, "POLYLINE", epsg, overwrite=True)

    # Calculate time-distance between origins Lyr and reference points
    # Get Geom of originsLyr
    # Convert to WGS84
    if epsg != 4326:
        originsWGS = project(
            originsLyr,
            os.path.join(os.path.dirname(output), 'origins_wgs84.shp'), 4326)
    else:
        originsWGS = originsLyr

    origLyr = feat_lyr(originsWGS)
    origPoint = []
    for line in arcpy.SearchCursor(origLyr):
        pnt = line.Shape.centroid

        origPoint.append((pnt.X, pnt.Y))

    # Get WGS REF POINTS
    if epsg != 4326:
        refWGS = project(
            REF_POINTS, os.path.join(os.path.dirname(output),
                                     'extent_wgs.shp'), 4326)
    else:
        refWGS = REF_POINTS

    refPointsLyr = feat_lyr(refWGS)
    refPoints = []
    for line in arcpy.SearchCursor(refPointsLyr):
        geom = line.getValue("Shape")

        for vector in geom:
            for pnt in vector:
                pnt_str = str(pnt).split(' ')
                refPoints.append((pnt_str[0], pnt_str[1]))

    # From that distances, get time intervals
    max_distance = get_max_dist(origPoint, refPoints)
    INTERVAL_RANGE = int(round(max_distance / NR_INTERVALS, 0))

    c = 0
    INTERVALS = []
    for i in range(NR_INTERVALS):
        INTERVALS.append(c + INTERVAL_RANGE)
        c += INTERVAL_RANGE

    # Run Service Area Tool
    service_area_polygon(networkDataset, rdvName, INTERVALS, originsLyr,
                         output)

    return output
Ejemplo n.º 8
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
Ejemplo n.º 9
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
Ejemplo n.º 10
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
Ejemplo n.º 11
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')
Ejemplo n.º 12
0
def clip_several_each_feature(rst_folder,
                              shp,
                              feature_id,
                              work,
                              template=None,
                              rst_file_format='.tif'):
    """
    Clip a folder of rasters by each feature in a feature class

    The rasters clipped for a feature will be in an individual folder
    """

    import arcpy
    import os

    from glass.cpu.arcg.lyr import feat_lyr
    from glass.cpu.arcg.lyr import rst_lyr
    from glass.cpu.arcg.anls.exct import select_by_attr
    from glass.cpu.arcg.mng.fld import type_fields
    from glass.oss.ops import create_folder
    from glass.pys.oss import lst_ff

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

    # ###### #
    # Do it! #
    # ###### #
    # Open feature class
    lyr_shp = feat_lyr(shp)

    # Create folder for some temporary files
    wTmp = create_folder(os.path.join(work, 'tmp'))

    # Split feature class in parts
    c = arcpy.SearchCursor(lyr_shp)
    l = c.next()
    features = {}

    # Get id's field type
    fld_type = type_fields(lyr_shp, field=feature_id)

    expression = '{fld}=\'{_id}\'' if str(fld_type) == 'String' else \
        '{fld}={_id}'

    del fields, f

    while l:
        fid = str(l.getValue(feature_id))

        selection = select_by_attr(
            lyr_shp, expression.format(fld=feature_id, _id=fid),
            os.path.join(wTmp, 'each_{}.shp'.format(fid)))

        f_lyr = feat_lyr(selection)
        features[fid] = f_lyr

        l = c.next()

    rasters = lst_ff(rst_folder, file_format='.tif')

    for raster in rasters:
        r_lyr = rst_lyr(raster)
        for feat in features:
            clip_rst = clip_raster(
                r_lyr, features[feat],
                os.path.join(work,
                             os.path.splitext(os.path.basename(feat))[0],
                             os.path.basename(raster)), template)
Ejemplo n.º 13
0
def euclidean_distance(shpRst,
                       cellsize,
                       outRst,
                       template=None,
                       boundary=None,
                       snap=None):
    """
    Euclidean distance from Spatial Analyst
    """

    from arcpy import env
    from arcpy.sa import *
    import os

    arcpy.CheckOutExtension('Spatial')

    from glass.prop.ff import vector_formats, raster_formats
    from glass.cpu.arcg.lyr import feat_lyr, rst_lyr

    path_to_output = outRst if not boundary else \
        os.path.join(
            os.path.dirname(outRst),
            '{n}_ext{f}'.format(
                n=os.path.splitext(os.path.basename(outRst))[0],
                f=os.path.splitext(os.path.basename(outRst))[1]
            )
        )

    inputFormat = os.path.splitext(shpRst)[1]
    if inputFormat in vector_formats():
        inLyr = feat_lyr(shpRst)

    elif inputFormat in raster_formats():
        inLyr = rst_lyr(shpRst)

    else:
        raise ValueError(
            'Could not identify if shpRst is a feature class or a raster')

    if template:
        tempEnvironment0 = env.extent
        env.extent = template

    if snap:
        tempSnap = env.snapRaster
        env.snapRaster = snap

    outEucDistance = EucDistance(inLyr, "", cellsize, "")
    outEucDistance.save(path_to_output)

    if template: env.extent = tempEnvironment0

    if snap: env.snapRaster = tempSnap

    if boundary:
        from glass.cpu.arcg.mng.rst.proc import clip_raster

        clipLyr = feat_lyr(boundary)

        clip_raster(path_to_output,
                    clipLyr,
                    outRst,
                    template=template,
                    snap=snap)
Ejemplo n.º 14
0
def geomArray_to_fc(array,
                    output,
                    GEOM_TYPE,
                    EPSG,
                    overwrite=True,
                    fields=None):
    """
    Convert a array as
    array = [
        {
            "FID" : 0,
            "OTHER_FIELDS" : value
            "GEOM" : [(x1, y1), ..., (xn, yn)]
        },
        ...,
        {
            "FID" : 1,
            "OTHER_FIELDS" : value
            "GEOM" : [(x1, y1), ..., (xn, yn)]
        },
    ]
    
    to a new Feature Class
    
    If fields, it should have a value like:
    {name : [type, length], name: [type, length]}
    """

    from glass.cpu.arcg.mng.featcls import create_feat_class
    from glass.cpu.arcg.lyr import feat_lyr
    from glass.cpu.arcg.mng.fld import add_field

    if overwrite: arcpy.env.overwriteOutput = True

    # Create a new Feature Class
    output = create_feat_class(output, GEOM_TYPE, EPSG)

    outLyr = feat_lyr(output)

    # Create fields
    if fields:
        if type(fields) != dict:
            raise ValueError('FIELDS should be a dict')

        else:
            for fld in fields:
                add_field(outLyr, fld, fields[fld][0], fields[fld][1])

    # Add things to the feature class
    cursor = arcpy.InsertCursor(outLyr)
    point = arcpy.CreateObject("Point")
    for line in array:
        vector = arcpy.CreateObject("Array")

        c = 0
        for pnt in line["GEOM"]:
            point.ID = c
            point.X = pnt[0]
            point.Y = pnt[1]
            vector.add(point)
            c += 1

        new_row = cursor.newRow()
        new_row.Shape = vector

        # Add field values
        if fields:
            for fld in fields:
                if fld in line:
                    new_row.setValue(fld, line[fld])

        cursor.insertRow(new_row)

        vector = 0

    return output
Ejemplo n.º 15
0
def viewshed_by_feat_class2(inRaster,
                            observerDataset,
                            feat_class_folder,
                            output_folder,
                            snapRst=None,
                            visibilityRadius=20000,
                            epsg=3763):
    """
    See for each feature class in a folder if it is possible to see a 
    interest object from all poins in each feature class
    
    Why this method is different from viewshed_by_feat_class?
    viewshed_by_feat_class uses viewshed tool of ArcGIS;
    This one will calculate the visibility point by point, when the script
    identifies that one point is observable from another, it stops.
    
    TO BE MANTAINED?
    """

    import arcpy
    import numpy
    import os

    from glass.oss.ops import create_folder
    from glass.prop.ff import vector_formats, raster_formats
    from glass.cpu.arcg.lyr import feat_lyr
    from glass.prop.rst import get_cell_coord
    from glass.prop.ext import rst_ext
    from glass.prop.rst import rst_shape, rst_distinct, get_nodata, get_cellsize
    from glass.anls.prox.bf import _buffer
    from glass.cpu.arcg.mng.rst.proc import clip_raster
    from glass.cpu.arcg.spanlst.surf import viewshed
    from glass.cpu.arcg.spanlst.rcls import reclassify
    from glass.cpu.arcg._3D.view import line_of_sight
    from glass.to.rst import shp_to_raster
    from glass.to.rst.arcg import array_to_raster
    from glass.to.shp.arcg import geomArray_to_fc
    from glass.fm.rst import toarray_varcmap as rst_to_array

    arcpy.CheckOutExtension('Spatial')
    arcpy.env.overwriteOutput = True

    # Check if observerDataset is a Raster or a Feature Class
    RASTER_FORMATS = raster_formats()
    VECTOR_FORMATS = vector_formats()
    observerFormat = os.path.splitext(observerDataset)[1]

    if observerFormat in VECTOR_FORMATS:
        from glass.cpu.arcg.anls.exct import clip

    elif observerFormat in RASTER_FORMATS:
        from glass.to.shp.arcg import rst_to_pnt
        from glass.to.shp import rst_to_polyg

        # If raster, get CELLSIZE of the observer dataset
        CELLSIZE = get_cellsize(observerDataset, gisApi='arcpy')
        REF_CELLSIZE = 500

        from glass.cpu.arcg.mng.sample import fishnet
        from glass.cpu.arcg.anls.ovlay import erase
        from glass.cpu.arcg.mng.feat import feat_to_pnt

    else:
        raise ValueError(('Could not identify if observerDataset is a raster '
                          'or a feature class'))

    # Create workspace for temporary files
    wTmp = create_folder(os.path.join(output_folder, 'tempfiles'))

    # When clipping the observerDataset (when it is a raster), there is a change
    # of obtaining a raster with more values than the original raster
    # Check values of the observerDataset
    UNIQUEVALUES = []
    if observerFormat in RASTER_FORMATS:
        for line in arcpy.SearchCursor(observerDataset):
            # TODO: Raster could not have attribute table
            value = int(line.getValue("Value"))

            if value not in UNIQUEVALUES:
                UNIQUEVALUES.append(value)

            else:
                continue

    # List feature classes
    arcpy.env.workspace = feat_class_folder
    fclasses = arcpy.ListFeatureClasses()

    for fc in fclasses:
        # Create Buffer
        fcBuffer = _buffer(
            fc,
            visibilityRadius,
            os.path.join(wTmp, os.path.basename(fc)),
        )

        # Clip inRaster
        clipInRst = clip_raster(inRaster,
                                fcBuffer,
                                os.path.join(
                                    wTmp, 'dem_{}{}'.format(
                                        os.path.splitext(
                                            os.path.basename(fc))[0],
                                        os.path.splitext(inRaster)[1])),
                                snap=snapRst,
                                clipGeom=True)

        # Clip observerDataset
        # If Raster, convert to points
        if observerDataset in VECTOR_FORMATS:
            clipObs = clip(
                observerDataset, fcBuffer,
                os.path.join(
                    wTmp, 'obs_{}{}'.format(
                        os.path.splitext(os.path.basename(fc))[0],
                        os.path.splitext(observerDataset)[1])))

        elif observerFormat in RASTER_FORMATS:
            # Clip Raster
            clipTmp = clip_raster(
                observerDataset,
                fcBuffer,
                os.path.join(
                    wTmp, 'obs_{}{}'.format(
                        os.path.splitext(os.path.basename(fc))[0],
                        os.path.splitext(observerDataset)[1])),
                snap=snapRst,
                clipGeom=True)

            # Check if clip has the same values that the original raster
            RST_UNIQUE = rst_distinct(clipTmp, gisApi='arcpy')
            if len(RST_UNIQUE) > len(UNIQUEVALUES):
                # Reclassify raster
                rules = {}
                for v in RST_UNIQUE:
                    if v in UNIQUEVALUES:
                        rules[v] = v
                    else:
                        rules[v] = 'NODATA'

                clipTmp = reclassify(
                    clipTmp,
                    'Value',
                    rules,
                    os.path.join(wTmp,
                                 'r_{}'.format(os.path.basename(clipTmp))),
                    template=clipTmp)

            if CELLSIZE < REF_CELLSIZE:
                # if cellsize if less than REF_CELLSIZE
                # Change cellsize to REF_CELLSIZE:

                # 1) Create fishnet REF_CELLSIZE
                fishNet = fishnet(os.path.join(
                    wTmp, 'fish_{}'.format(os.path.basename(fc))),
                                  clipTmp,
                                  cellWidth=REF_CELLSIZE,
                                  cellHeight=REF_CELLSIZE)

                # 2) Erase areas with NoData Values
                # Raster to shp
                cls_intPolygon = rst_to_polyg(
                    clipTmp,
                    os.path.join(wTmp,
                                 'cls_int_{}'.format(os.path.basename(fc))),
                    gisApi='arcpy')

                # - Erase areas of the fishnet that have nodata values
                # in the raster
                tmpErase = erase(
                    fishNet, cls_intPolygon,
                    os.path.join(wTmp,
                                 'nozones_{}'.format(os.path.basename(fc))))

                trueErase = erase(
                    fishNet, tmpErase,
                    os.path.join(wTmp,
                                 'fishint_{}'.format(os.path.basename(fc))))

                # 3) Convert erased fishnet to points
                clipObs = feat_to_pnt(
                    trueErase,
                    os.path.join(wTmp, 'obs_{}'.format(os.path.basename(fc))),
                    pnt_position="INSIDE")

            else:
                clipObs = rst_to_pnt(
                    clipTmp,
                    os.path.join(wTmp, 'obs_{}'.format(os.path.basename(fc))))

        # Calculate visibility
        # Boundary to raster
        boundRst = shp_to_raster(
            fc,
            'FID',
            CELLSIZE,
            None,
            os.path.join(
                wTmp, '{}_{}'.format(
                    os.path.splitext(os.path.basename(fc))[0],
                    os.path.splitext(observerDataset)[1])),
            snap=clipInRst,
            api='arcpy')

        noDataVal = get_nodata(boundRst, gisApi='arcpy')

        boundArray = rst_to_array(boundRst)

        # Raster to array
        # For each cell, get cell position and create line of sight
        shape = rst_shape(boundRst, gisApi='arcpy')
        xmin, xmax, ymin, ymax = rst_ext(boundRst, gisApi='arcpy2')

        visibilityArray = numpy.zeros((shape[0], shape[1]))

        numpy.copyto(visibilityArray, boundArray, 'unsafe',
                     boundArray == noDataVal)

        for l in range(len(visibilityArray)):
            for c in range(len(visibilityArray[l])):
                if visibilityArray[l][c] == noDataVal:
                    continue

                # Get cell position
                x, y = get_cell_coord(l, c, xmin, ymin, CELLSIZE, CELLSIZE)

                # Get Line of sight
                cursor = arcpy.SearchCursor(clipObs)
                for line in cursor:
                    FID = line.getValue("FID")
                    geom = line.Shape.centroid
                    sightArray = [
                        {
                            "FID": 0,
                            "GEOM": [(x, y), (geom.X, geom.Y)]
                        },
                    ]

                    lineSight = geomArray_to_fc(
                        sightArray,
                        os.path.join(
                            wTmp, 'ls_{}_{}_{}_{}{}'.format(
                                os.path.splitext(os.path.basename(fc))[0],
                                str(l), str(c), str(FID),
                                os.path.splitext(fc)[1])), "POLYLINE", epsg)

                    lineSightRes = line_of_sight(
                        clipInRst, lineSight,
                        os.path.join(
                            wTmp, 'lsr_{}_{}_{}_{}{}'.format(
                                os.path.splitext(os.path.basename(fc))[0],
                                str(l), str(c), str(FID),
                                os.path.splitext(fc)[1])))

                    lyrLineSight = feat_lyr(lineSightRes)

                    cs = arcpy.SearchCursor(lyrLineSight)
                    lnh = cs.next()
                    cnt = 0
                    while cnt == 0:
                        try:
                            vis = lnh.getValue("TarIsVis")
                        except:
                            pass
                        cnt += 1

                    if vis == 1:
                        visibilityArray[l][c] = 1
                        break
                    else:
                        continue

        # Generate Raster with visibility data
        visibilityRst = array_to_raster(
            visibilityArray, xmin, CELLSIZE, CELLSIZE,
            os.path.join(
                output_folder, 'vis_{}{}'.format(
                    os.path.splitext(os.path.basename(fc))[0],
                    os.path.splitext(clipInRst)[1])))

    return output_folder