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
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
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
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)
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')
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) }
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
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