Example #1
0
def range_score(raster, output, MAX=True, __template=None):
    """
    Calculate a Range Score of a Raster
    
    If Max, major values will be the major values in the normalized raster;
    Else, major values will be the minor values in the normalizes raster.
    """
    
    import os
    from gasp.oss             import get_filename
    from gasp.cpu.arcg.lyr    import rst_lyr
    from gasp.prop.rst        import rst_stats
    from gasp.spanlst.algebra import rstcalc
    
    lyr = rst_lyr(raster)
    
    __max = rst_stats(lyr, api='arcpy')["MAX"]
    __min = rst_stats(lyr, api='arcpy')["MIN"]
    
    express = '({rst} - {_min}) / ({_max} - {_min})' if MAX else \
        '({_max} - {rst}) / ({_max} - {_min})'
    
    rstcalc(
        express.format(
            _min=str(__min), _max=str(__max),
            rst=get_filename(raster)
        ),
        output, api='arcpy'
    )
    
    return output
Example #2
0
def maximum_score(raster, output, MAX=True, __template=None):
    """
    Calculate a Maximum Score of a Raster
    
    If Max, major values will be the major values in the normalized raster;
    Else, major values will be the minor values in the normalizes raster.
    """
    
    import os
    from gasp.oss             import get_filename
    from gasp.cpu.arcg.lyr    import rst_lyr
    from gasp.prop.rst        import rst_stats
    from gasp.spanlst.algebra import rstcalc
    
    lyr = rst_lyr(raster)
    
    __max = rst_stats(lyr, api='arcpy')["MAX"]
    
    express = '{rst} / {_max}' if MAX else '1 - ({rst} / {_max})'
    
    rstcalc(
        express.format(
            rst=get_filename(raster),
            _max=str(__max)
        ),
        output, template=__template, api='arcpy'
    )
    
    return output
Example #3
0
def acumulated_cost(cst_surface, dest_pnt, cst_dist):
    """
    Uses a cost surface to estimate the time between each cell and the 
    close destination
    """

    from gasp.spanlst.algebra import rstcalc
    from gasp.spanlst.dist import rcost
    from gasp.to.rst import rst_to_grs, grs_to_rst
    from gasp.to.shp.grs import shp_to_grs

    # Add Cost Surface to GRASS GIS
    rst_to_grs(cst_surface, 'cst_surf')
    # Add Destination To GRASS
    shp_to_grs(dest_pnt, 'destination')
    # Execute r.cost
    rcost('cst_surf', 'destination', 'cst_dist')
    # Convert to minutes
    rstcalc('cst_dist / 60.0', 'CstDistMin', api="grass")
    # Export result
    grs_to_rst('CstDistMin', cst_dist)

    return cst_dist
Example #4
0
def cost_surface(dem,
                 lulc,
                 cls_lulc,
                 prod_lulc,
                 roads,
                 kph,
                 barr,
                 grass_location,
                 output,
                 grass_path=None):
    """
    Tool for make a cost surface based on the roads, slope, land use and
    physical barriers. ach cell has a value that represents the resistance to
    the movement.
    """

    import os

    from gasp.oss.ops import create_folder
    from gasp.os import os_name
    from gasp.session import run_grass
    from gasp.prop.rst import get_cellsize
    from gasp.prop.rst import rst_distinct

    from .constants import lulc_weight
    from .constants import get_slope_categories
    """
    Auxiliar Methods
    """
    def edit_lulc(shp, fld_cls, new_cls):
        FT_TF_GRASS(shp, 'lulc', 'None')
        add_field('lulc', 'leg', 'INT')
        for key in new_cls.keys():
            l = new_cls[key]['cls']
            sql = " OR ".join([
                "{campo}='{value}'".format(campo=fld_cls, value=i) for i in l
            ])
            update_table('lulc', 'leg', int(key), sql)
        return {'shp': 'lulc', 'fld': 'leg'}

    def combine_to_cost(rst_combined, lst_rst, work, slope_weight,
                        rdv_cos_weight, cellsize, mode_movement):
        # The tool r.report doesn't work properly, for that we need some aditional information
        l = []
        for i in lst_rst:
            FT_TF_GRASS(i, os.path.join(work, i + '.tif'), 'None')
            values = rst_distinct(os.path.join(work, i + '.tif'),
                                  gisApi='gdal')
            l.append(min(values))
        # ******
        # Now, we can procede normaly
        txt_file = os.path.join(work, 'text_combine.txt')
        raster_report(rst_combined, txt_file)
        open_txt = open(txt_file, 'r')
        c = 0
        dic_combine = {}
        for line in open_txt.readlines():
            try:
                if c == 4:
                    dic_combine[0] = [str(l[0]), str(l[1])]
                elif c >= 5:
                    pl = line.split('|')
                    cat = pl[2].split('; ')
                    cat1 = cat[0].split(' ')
                    cat2 = cat[1].split(' ')
                    dic_combine[int(pl[1])] = [cat1[1], cat2[1]]
                c += 1
            except:
                break

        cst_dic = {}
        for key in dic_combine.keys():
            cls_slope = int(dic_combine[key][0])
            cos_vias = int(dic_combine[key][1])
            if cos_vias >= 6:
                weight4slope = slope_weight[cls_slope]['rdv']
                if mode_movement == 'pedestrian':
                    weight4other = (3600.0 * cellsize) / (5.0 * 1000.0)
                else:
                    weight4other = (3600.0 * cellsize) / (cos_vias * 1000.0)
            else:
                weight4slope = slope_weight[cls_slope]['cos']
                weight4other = rdv_cos_weight[cos_vias]['weight']
            cst_dic[key] = (weight4slope * weight4other) * 10000000.0
        return cst_dic

    def Rules4CstSurface(dic, work):
        txt = open(os.path.join(work, 'cst_surface.txt'), 'w')
        for key in dic.keys():
            txt.write('{cat}  = {cst}\n'.format(cat=str(key),
                                                cst=str(dic[key])))
        txt.close()
        return os.path.join(work, 'cst_surface.txt')

    """
    Prepare GRASS GIS Environment
    """
    workspace = os.path.dirname(grass_location)
    location = os.path.basename(grass_location)
    # Start GRASS GIS Engine
    grass_base = run_grass(workspace, location, dem, win_path=grass_path)
    import grass.script as grass
    import grass.script.setup as gsetup
    gsetup.init(grass_base, workspace, location, 'PERMANENT')

    # Import GRASS GIS Modules
    from gasp.cpu.grs import grass_converter
    from gasp.spanlst.surf import slope
    from gasp.spanlst.rcls import reclassify
    from gasp.spanlst.rcls import interval_rules
    from gasp.spanlst.rcls import category_rules
    from gasp.spanlst.rcls import grass_set_null
    from gasp.mng.grstbl import add_field, update_table
    from gasp.anls.ovlay import union
    from gasp.to.rst import rst_to_grs, grs_to_rst
    from gasp.to.rst import shp_to_raster
    from gasp.to.shp.grs import shp_to_grs
    from gasp.cpu.grs.spanlst import mosaic_raster
    from gasp.spanlst.local import combine
    from gasp.spanlst.algebra import rstcalc
    from gasp.cpu.grs.spanlst import raster_report
    """Global variables"""
    # Workspace for temporary files
    wTmp = create_folder(os.path.join(workspace, 'tmp'))

    # Cellsize
    cellsize = float(get_cellsize(dem), gisApi='gdal')
    # Land Use Land Cover weights
    lulcWeight = lulc_weight(prod_lulc, cellsize)
    # Slope classes and weights
    slope_cls = get_slope_categories()
    """Make Cost Surface"""
    # Generate slope raster
    rst_to_grs(dem, 'dem')
    slope('dem', 'rst_slope', api="pygrass")

    # Reclassify Slope
    rulesSlope = interval_rules(slope_cls, os.path.join(wTmp, 'slope.txt'))
    reclassify('rst_slope', 'recls_slope', rulesSlope)

    # LULC - Dissolve, union with barriers and conversion to raster
    lulc_shp = edit_lulc(lulc, cls_lulc, lulc_weight)
    shp_to_grs(barr, 'barriers')
    union(lulc_shp['shp'], 'barriers', 'barrcos', api_gis="grass")
    update_table('barrcos', 'a_' + lulc_shp['fld'], 99, 'b_cat=1')
    shp_to_raster('barrcos',
                  'a_' + lulc_shp['fld'],
                  None,
                  None,
                  'rst_barrcos',
                  api='pygrass')

    # Reclassify this raster - convert the values 99 to NULL or NODATA
    grass_set_null('rst_barrcos', 99)

    # Add the roads layer to the GRASS GIS
    shp_to_grs(roads, 'rdv')
    if kph == 'pedestrian':
        add_field('rdv', 'foot', 'INT')
        update_table('rdv', 'foot', 50, 'foot IS NULL')
        shp_to_raster('rdv', 'foot', None, None, 'rst_rdv', api='pygrass')
    else:
        shp_to_raster('rdv', kph, None, None, 'rst_rdv', api='pygrass')

    # Merge LULC/BARR and Roads
    mosaic_raster('rst_rdv', 'rst_barrcos', 'rdv_barrcos')

    # Combine LULC/BARR/ROADS with Slope
    combine('recls_slope', 'rdv_barrcos', 'rst_combine', api="pygrass")
    """
    Estimating cost for every combination at rst_combine
    The order of the rasters on the following list has to be the same of
    GRASS Combine"""
    cst = combine_to_cost('rst_combine', ['recls_slope', 'rdv_barrcos'], wTmp,
                          slope_cls, lulc_weight, cell_size, kph)

    # Reclassify combined rst
    rulesSurface = category_rules(cst, os.path.join('r_surface.txt'))
    reclassify('rst_combine', 'cst_tmp', rulesSurface)
    rstcalc('cst_tmp / 10000000.0', 'cst_surface', api='pygrass')
    grs_to_rst('cst_surface', output)
Example #5
0
def cstDistance_with_motorway(cst_surface, motorway, fld_motorway, nodes_start,
                              nodes_end, pnt_destiny, grass_location,
                              isolines):
    """
    Produce a surface representing the acumulated cost of each cell to a
    destination point considering the false intersections caused by a non
    planar graph
    """

    import os

    from gasp.oss.ops import create_folder
    from gasp.prop.ff import drv_name
    from gasp.cpu.grs.spanlst import rseries
    from gasp.spanlst.algebra import rstcalc
    from gasp.spanlst.dist import rcost
    from gasp.to.rst import rst_to_grs
    from gasp.to.rst import shp_to_raster
    from gasp.cpu.gdl.sampling import gdal_values_to_points
    from pysage.tools_thru_api.gdal.ogr import OGR_CreateNewShape
    """
    Auxiliar Methods
    """
    def dist_to_nodes(pnt_shp, cstSurface, string, w):
        nodes = ogr.GetDriverByName(drv_name(pnt_shp)).Open(pnt_shp, 0)

        nodesLyr = nodes.GetLayer()

        c = 0
        dicNodes = {}
        for pnt in nodesLyr:
            geom = pnt.GetGeometryRef()
            point = geom.ExportToWkb()
            OGR_CreateNewShape(
                OGR_GetDriverName(pnt_shp),
                os.path.join(w, '{pnt}_{o}.shp'.format(pnt=string, o=str(c))),
                ogr.wkbPoint, [point])
            FT_TF_GRASS(
                os.path.join(w, '{pnt}_{o}.shp'.format(pnt=string, o=str(c))),
                '{pnt}_{o}'.format(pnt=string, o=str(c)), 'None')
            GRASS_CostDistance(cstSurface, '{pnt}_{o}'.format(pnt=string,
                                                              o=str(c)),
                               'cst_{pnt}_{a}'.format(pnt=string, a=str(c)))
            dicNodes['{pnt}_{o}'.format(pnt=string, o=str(c))] = [
                os.path.join(w, '{pnt}_{o}.shp'.format(pnt=string, o=str(c))),
                'cst_{pnt}_{a}'.format(pnt=string, a=str(c))
            ]
            c += 1
        return dicNodes

    """GRASS GIS Configuration"""
    # Workspace for temporary files
    wTmp = create_folder(os.path.join(os.path.dirname(grass_location), 'tmp'))
    """Make Accessibility Map"""
    # Add Cost Surface to GRASS GIS
    convert(cst_surface, 'cst_surface')
    # Add Destination To GRASS
    convert(pnt_destiny, 'destination')

    # Run r.cost with only with a secundary roads network
    rcost('cst_surface', 'destination', 'cst_dist_secun')

    # We have to know if the path through motorway implies minor cost.
    # Add primary roads to grass
    convert(motorway, 'rdv_prim', 'None')

    # We need a cost surface only with the cost of motorway roads
    shp_to_raster('rdv_prim',
                  fld_motorway,
                  None,
                  None,
                  'rst_rdv',
                  api='pygrass')
    rstcalc('(3600.0 * {cs}) / (rst_rdv * 1000.0)'.format(
        cs=get_cellsize(cst_surface, gisApi='gdal')),
            'cst_motorway',
            api='grass')

    # For each node of entrance into a motorway, we need to know:
    # - the distance to the entrance node;
    # - the distance between the entrance and every exit node
    # - the distance between the exit and the destination
    # Geting the distance to the entrance node
    entranceNodes = dist_to_nodes(nodes_start, 'cst_surface', 'start', wTmp)
    # Geting the distances to all entrance nodes
    exitNodes = dist_to_nodes(nodes_end, 'cst_surface', 'exit', wTmp)

    # Getting the values needed
    for start_pnt in entranceNodes.keys():
        for exit_pnt in exitNodes.keys():
            GRASS_CostDistance(
                'cst_motorway', exit_pnt,
                'cst2exit_{a}_{b}'.format(a=str(start_pnt[-1]),
                                          b=str(exit_pnt[-1])))
            FT_TF_GRASS(
                'cst2exit_{a}_{b}'.format(a=str(start_pnt[-1]),
                                          b=str(exit_pnt[-1])),
                os.path.join(
                    wTmp, 'cst2exit_{a}_{b}.tif'.format(a=str(start_pnt[-1]),
                                                        b=str(exit_pnt[-1]))),
                'None')
            cst_start_exit = GDAL_ExtractValuesByPoint(
                entranceNodes[start_pnt][0],
                os.path.join(
                    wTmp, 'cst2exit_{a}_{b}.tif'.format(a=str(start_pnt[-1]),
                                                        b=str(exit_pnt[-1]))))
            if os.path.isfile(
                    os.path.join(wTmp,
                                 exitNodes[exit_pnt][1] + '.tif')) == False:
                FT_TF_GRASS(
                    exitNodes[exit_pnt][1],
                    os.path.join(wTmp, exitNodes[exit_pnt][1] + '.tif'),
                    'None')
            cst_exit_destination = GDAL_ExtractValuesByPoint(
                pnt_destiny, os.path.join(wTmp,
                                          exitNodes[exit_pnt][1] + '.tif'))
            GRASS_RasterCalculator(
                '{rst} + {a} + {b}'.format(rst=entranceNodes[start_pnt][1],
                                           a=str(cst_start_exit[0]),
                                           b=str(min(cst_exit_destination))),
                'cst_path_{a}_{b}'.format(a=str(start_pnt[-1]),
                                          b=str(exit_pnt[-1])))
            lst_outputs.append('cst_path_{a}_{b}'.format(a=str(start_pnt[-1]),
                                                         b=str(exit_pnt[-1])))
    lst_outputs.append('cst_dist_secun')
    rseries(lst_outputs, 'isocronas', 'minimum')
Example #6
0
def grs_rst_roads(osmdb, lineTbl, polyTbl, dataFolder, LULC_CLS):
    """
    Raster Roads for GRASS
    """

    import os
    import datetime
    from gasp.to.shp.grs import shp_to_grs, sqlite_to_shp
    from gasp.to.rst import shp_to_raster
    from gasp.sql.anls.prox import splite_buffer
    from gasp.sql.mng.tbl import row_num

    time_a = datetime.datetime.now().replace(microsecond=0)
    NR = row_num(osmdb, lineTbl, where="roads IS NOT NULL", api='sqlite')
    time_b = datetime.datetime.now().replace(microsecond=0)

    if not NR: return None, {0: ('count_rows_roads', time_b - time_a)}

    roadFile = splite_buffer(
        osmdb,
        lineTbl,
        "bf_roads",
        "geometry",
        'bfu_roads',
        #os.path.join(dataFolder, 'bf_roads.gml'),
        whrClause="roads IS NOT NULL",
        outTblIsFile=None,
        dissolve="ALL")
    time_c = datetime.datetime.now().replace(microsecond=0)

    #roadGrs = shp_to_grs(roadFile, "bf_roads", filterByReg=True, asCMD=True)
    roadGrs = sqlite_to_shp(osmdb, "bfu_roads", 'bf_roads', notTable=True)
    time_d = datetime.datetime.now().replace(microsecond=0)
    roadRst = shp_to_raster(roadGrs,
                            int(LULC_CLS),
                            None,
                            None,
                            "rst_roads",
                            api="grass")
    time_e = datetime.datetime.now().replace(microsecond=0)

    # Builds to GRASS and to RASTER
    NB = row_num(osmdb, polyTbl, where="building IS NOT NULL", api='sqlite')
    time_f = datetime.datetime.now().replace(microsecond=0)

    if NB:
        from gasp.spanlst.algebra import rstcalc
        from gasp.spanlst.rcls import set_null, null_to_value

        buildsShp = sqlite_to_shp(osmdb,
                                  polyTbl,
                                  "all_builds",
                                  where="building IS NOT NULL",
                                  notTable=True)
        time_g = datetime.datetime.now().replace(microsecond=0)

        buildsRst = shp_to_raster(buildsShp,
                                  1,
                                  None,
                                  None,
                                  "rst_builds",
                                  api="grass")
        time_h = datetime.datetime.now().replace(microsecond=0)

        # Buildings to nodata | Nodata to 0
        null_to_value(buildsRst, 0, as_cmd=True)
        time_i = datetime.datetime.now().replace(microsecond=0)
        set_null(buildsRst, 1, ascmd=True)
        time_j = datetime.datetime.now().replace(microsecond=0)

        # Do the math: roads + builds | if builds and roads at the same cell
        # cell will be null in the road layer
        roadsRes = rstcalc("{} + {}".format(roadRst, buildsRst),
                           "cls_roads",
                           api="grass")
        time_l = datetime.datetime.now().replace(microsecond=0)

        return {
            LULC_CLS: roadsRes
        }, {
            0: ('count_rows_roads', time_b - time_a),
            1: ('buffer_roads', time_c - time_b),
            2: ('import_roads', time_d - time_c),
            3: ('roads_to_rst', time_e - time_d),
            4: ('count_build', time_f - time_e),
            5: ('builds_to_grs', time_g - time_f),
            6: ('builds_to_rst', time_h - time_g),
            7: ('bnull_to_val', time_i - time_h),
            8: ('builds_to_nd', time_j - time_i),
            9: ('roads_build_mc', time_l - time_j)
        }

    else:
        return {
            LULC_CLS: roadRst
        }, {
            0: ('count_rows_roads', time_b - time_a),
            1: ('buffer_roads', time_c - time_b),
            2: ('import_roads', time_d - time_c),
            3: ('roads_to_rst', time_e - time_d),
            4: ('count_build', time_f - time_e)
        }
Example #7
0
File: grs.py Project: zonakre/gasp
def make_DEM(grass_workspace,
             data,
             field,
             output,
             extent_template,
             method="IDW"):
    """
    Create Digital Elevation Model
    
    Methods Available:
    * IDW;
    * BSPLINE;
    * SPLINE;
    * CONTOUR
    """

    from gasp.oss import get_filename
    from gasp.session import run_grass
    from gasp.prop.rst import get_epsg_raster

    LOC_NAME = get_filename(data, forceLower=True)[:5] + "_loc"

    # Get EPSG From Raster
    EPSG = get_epsg_raster(extent_template)

    # Create GRASS GIS Location
    grass_base = run_grass(grass_workspace, location=LOC_NAME, srs=EPSG)

    # Start GRASS GIS Session
    import grass.script as grass
    import grass.script.setup as gsetup
    gsetup.init(grass_base, grass_workspace, LOC_NAME, 'PERMANENT')

    # IMPORT GRASS GIS MODULES #
    from gasp.to.rst import rst_to_grs, grs_to_rst
    from gasp.to.shp.grs import shp_to_grs
    from gasp.prop.grs import rst_to_region

    # Configure region
    rst_to_grs(extent_template, 'extent')
    rst_to_region('extent')

    # Convert elevation "data" to GRASS Vector
    elv = shp_to_grs(data, 'elevation')

    OUTPUT_NAME = get_filename(output, forceLower=True)

    if method == "BSPLINE":
        # Convert to points
        from gasp.cpu.grs.mng.feat import feat_vertex_to_pnt
        from gasp.spanlst.interp import bspline

        elev_pnt = feat_vertex_to_pnt(elv, "elev_pnt", nodes=None)

        outRst = bspline(elev_pnt, field, OUTPUT_NAME, lyrN=1, asCMD=True)

    elif method == "SPLINE":
        # Convert to points
        from gasp.cpu.grs.mng.feat import feat_vertex_to_pnt
        from gasp.spanlst.interp import surfrst

        elev_pnt = feat_vertex_to_pnt(elv, "elev_pnt", nodes=None)

        outRst = surfrst(elev_pnt, field, OUTPUT_NAME, lyrN=1, ascmd=True)

    elif method == "CONTOUR":
        from gasp.to.rst import shp_to_raster
        from gasp.spanlst.interp import surfcontour

        # Elevation (GRASS Vector) to Raster
        elevRst = shp_to_raster(elv,
                                field,
                                None,
                                None,
                                'rst_elevation',
                                api="pygrass")

        # Run Interpolator
        outRst = surfcontour(elevRst, OUTPUT_NAME, ascmd=True)

    elif method == "IDW":
        from gasp.spanlst.interp import ridw
        from gasp.spanlst.algebra import rstcalc
        from gasp.to.rst import shp_to_raster

        # Elevation (GRASS Vector) to Raster
        elevRst = shp_to_raster(elv,
                                field,
                                None,
                                None,
                                'rst_elevation',
                                api='pygrass')
        # Multiply cells values by 100 000.0
        rstcalc('int(rst_elevation * 100000)', 'rst_elev_int', api='pygrass')
        # Run IDW to generate the new DEM
        ridw('rst_elev_int', 'dem_int', numberPoints=15)
        # DEM to Float
        rstcalc('dem_int / 100000.0', OUTPUT_NAME, api='pygrass')

    # Export DEM to a file outside GRASS Workspace
    grs_to_rst(OUTPUT_NAME, output)

    return output
Example #8
0
def generate_waterlines(mdt,
                        waterbodies,
                        accumulation_value=500,
                        workspace=None):
    """
    Generate Water Bodies lines
    """

    import os
    from gasp.oss import get_fileformat
    from gasp.cpu.arcg.lyr import rst_lyr
    from gasp.prop.ff import vector_formats, raster_formats
    from gasp.spanlst.algebra import rstcalc
    from gasp.cpu.arcg.spanlst.hydro import fill
    from gasp.cpu.arcg.spanlst.hydro import flow_accumulation
    from gasp.cpu.arcg.spanlst.hydro import flow_direction
    from gasp.cpu.arcg.spanlst.hydro import stream_to_feature

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

    raster_format = os.path.splitext(os.path.basename(waterbodies))[1]

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

    fill_rst = fill(mdt, 'flow_raster{}'.format(raster_format), template=mdt)

    dire_rst = flow_direction(fill_rst,
                              'direction_raster{}'.format(raster_format),
                              template=mdt)

    flow_acc = flow_accumulation(dire_rst,
                                 'flow_raster{}'.format(raster_format),
                                 template=mdt)

    # Split water bodies from the other accumulation data
    lyr_flow = rst_lyr(flow_acc)

    outFormat = os.path.splitext(os.path.basename(waterbodies))[1]
    rstFormat = raster_formats()
    vecFormat = vector_formats()

    waterRst = waterbodies if outFormat in rstFormat else \
        os.path.join(
            workspace,
            os.path.splitext(os.path.basename(waterbodies))[0] + raster_format
        ) if outFormat in vecFormat else None

    if not waterRst:
        raise ValueError('Your output is not a raster and is not a vector')

    waterRst = rstcalc('{r} > {a}'.format(r=os.path.splitext(
        os.path.basename(flow_acc))[0],
                                          a=str(accumulation_value)),
                       waterRst,
                       template=mdt,
                       api='arcpy')

    if outFormat in vecFormat:
        stream_to_feature(waterRst, dire_rst, waterbodies)

        return waterbodies

    else:
        return waterRst