def main(): if options['option'] == 'add': num_bound = grass.vector_info_topo(map = options['input'])['boundaries'] if num_bound == 0: grass.fatal(_("Input vector map contains no boundaries.")) grass.exec_command("v.category", type = 'area', **options) sys.exit(0)
def main(): if options["option"] == "add": num_bound = gscript.vector_info_topo(map=options["input"])["boundaries"] if num_bound == 0: gscript.fatal(_("Input vector map contains no boundaries.")) gscript.exec_command("v.category", type="area", **options) sys.exit(0)
def test_tp(filename, link=False, outdir=None): """!Test VFK file using GRASS GIS Print geometry test report to stdout @return True on success False on failure """ print "\nSimple Features Test (GRASS-OGR %s):" % ("link" if link else "import") print '-' * 80 layers = [] for row in grass.read_command('v.external', flags='t', dsn=filename, quiet=True, stderr = None).splitlines(): layers.append(row.split(',')) if link: gmodule = 'v.external' else: gmodule = 'v.in.ogr' if not outdir: outdir = os.path.dirname(filename) for layer in layers: if layer[1] == 'none': continue # import or link layer ret = grass.read_command(gmodule, dsn=filename, layer=layer[0], overwrite=True, quiet=True, stderr=grass.STDOUT).splitlines() # generate graphics output image_path = os.path.join(outdir, layer[0] + '.png') grass.run_command('d.mon', start = 'cairo', output = image_path, overwrite=True) grass.run_command('g.region', vect = layer[0]) grass.run_command('d.erase') grass.run_command('d.vect', map = layer[0], quiet = True) grass.run_command('d.text', text = layer[0], at = '1,95', color = 'black') grass.run_command('d.mon', stop = 'cairo') nempty = 0 for line in ret: if 'without geometry' in line: nempty += int(line.split(' ')[1]) vinfo = grass.vector_info_topo(layer[0]) if layer[1] == 'polygon': nfeat = vinfo['areas'] elif layer[1] == 'linestring': nfeat = vinfo['lines'] else: nfeat = vinfo['points'] report_geom(layer[0], layer[1], 0, nempty, nfeat + nempty) print '-' * 80
def xdrawing_roads(draw_vector_append_name, env, update, giface, **kwargs): gscript.run_command('v.generalize', input=draw_vector_append_name, output='smooth', threshold=10, method='snakes', env=env) env2 = get_environment(raster='buncombe') gscript.run_command('v.to.rast', input='smooth', output='road', type='line', use='val', env=env2) #gscript.mapcalc('roads_patch = if(isnull(road), roads, road)', env=env2) #gscript.run_command('r.neighbors', flags='c', input='roads_patch', output='road_dens_edit', size=25, method='average', env=env2) #gscript.mapcalc('road_dens_perc_edit = 100 * road_dens_edit', env=env2) #gscript.run_command('r.colors', map='road_dens_perc_edit,road_dens_perc', color='byr', env=env2) gscript.run_command('r.grow.distance', input='road', distance='buffer', env=env2) gscript.mapcalc('stimulus_roads = if(buffer > 500, 0, graph(buffer, 0, 0.7, 200,0.5, 500,0.3))', env=env2) gscript.run_command('r.colors', map='stimulus_roads', color='reds', env=env) params = [] ff = gscript.find_file(name='appended', element='vector') if ff and ff['fullname'] and gscript.vector_info_topo('appended')['lines'] > 0: params.append('stimulus=stimulus_roads') futures(params, giface, update)
def run_drain(scanned_elev, env, points=None, **kwargs): drain = "drain" if not points: elev_no_points = "scan_saved" points = "points" import analyses from tangible_utils import get_environment env2 = get_environment(raster=elev_no_points) analyses.change_detection( "scan_saved", scanned_elev, points, height_threshold=[10, 100], cells_threshold=[5, 50], add=True, max_detected=5, debug=True, env=env, ) else: elev_no_points = scanned_elev env2 = env # if points detected if gs.vector_info_topo("points")["points"]: gs.run_command( "r.drain", input=elev_no_points, output=drain, drain=drain, start_points=points, env=env2, ) else: # create empty vector gs.run_command("v.edit", map=drain, tool="create", env=env)
def main(): raster = options['raster'] maskcats = options['maskcats'] vector = options['vector'] layer = options['layer'] cats = options['cats'] where = options['where'] remove = flags['r'] invert = flags['i'] if not remove and not raster and not vector: grass.fatal( _("Either parameter <raster> ot parameter <vector> is required")) mapset = grass.gisenv()['MAPSET'] exists = bool( grass.find_file('MASK', element='cell', mapset=mapset)['file']) if remove: # -> remove if exists: grass.run_command('g.remove', flags='f', quiet=True, type='raster', name='MASK') grass.message(_("Raster MASK removed")) else: grass.fatal(_("No existing MASK to remove")) else: # -> create if exists: if not grass.overwrite(): grass.fatal( _("MASK already found in current mapset. Delete first or overwrite." )) else: grass.warning(_("MASK already exists and will be overwritten")) grass.run_command('g.remove', flags='f', quiet=True, type='raster', name='MASK') if raster: # check if input raster exists if not grass.find_file(raster)['file']: grass.fatal(_("Raster map <%s> not found") % raster) if maskcats != '*' and not remove: if grass.raster_info(raster)['datatype'] != "CELL": grass.fatal( _("The raster map <%s> must be integer (CELL type) " " in order to use the 'maskcats' parameter") % raster) p = grass.feed_command('r.reclass', input=raster, output='MASK', overwrite=True, rules='-') p.stdin.write("%s = 1" % maskcats) p.stdin.close() p.wait() elif vector: vector_name = grass.find_file(vector, 'vector')['fullname'] if not vector_name: grass.fatal(_("Vector map <%s> not found") % vector) # parser bug? if len(cats) == 0: cats = None if len(where) == 0: where = None if grass.vector_info_topo(vector_name)['areas'] < 1: grass.warning( _("No area found in vector map <%s>. " "Creating a convex hull for MASK.") % vector_name) global tmp_hull tmp_hull = "tmp_hull_%d" % os.getpid() to_rast_input = tmp_hull # force 'flat' convex hull for 3D vector maps try: grass.run_command('v.hull', flags='f', quiet=True, input=vector_name, output=tmp_hull, layer=layer, cats=cats, where=where) except CalledModuleError: grass.fatal( _("Unable to create a convex hull for vector map <%s>") % vector_name) else: to_rast_input = vector_name env = os.environ.copy() if grass.verbosity() > 1: env['GRASS_VERBOSE'] = '1' grass.run_command('v.to.rast', input=to_rast_input, layer=layer, output='MASK', use='val', val='1', type='area', cats=cats, where=where, env=env) if invert: global tmp tmp = "r_mask_%d" % os.getpid() grass.run_command('g.rename', raster=('MASK', tmp), quiet=True) grass.message(_("Creating inverted raster MASK...")) grass.mapcalc("MASK = if(isnull($tmp), 1, null())", tmp=tmp) grass.verbose(_("Inverted raster MASK created")) else: grass.verbose(_("Raster MASK created")) grass.message( _("All subsequent raster operations will be limited to " "the MASK area. Removing or renaming raster map named " "'MASK' will restore raster operations to normal."))
def main(): raster = options["raster"] maskcats = options["maskcats"] vector = options["vector"] layer = options["layer"] cats = options["cats"] where = options["where"] remove = flags["r"] invert = flags["i"] if not remove and not raster and not vector: grass.fatal(_("Either parameter <raster> ot parameter <vector> is required")) mapset = grass.gisenv()["MAPSET"] exists = bool(grass.find_file("MASK", element="cell", mapset=mapset)["file"]) if remove: # -> remove if exists: grass.run_command("g.remove", flags="f", quiet=True, type="rast", pattern="MASK") grass.message(_("Raster MASK removed")) else: grass.fatal(_("No existing MASK to remove")) else: # -> create if exists: if not grass.overwrite(): grass.fatal(_("MASK already found in current mapset. Delete first or overwrite.")) else: grass.warning(_("MASK already exists and will be overwritten")) grass.run_command("g.remove", flags="f", quiet=True, type="rast", pattern="MASK") if raster: # check if input raster exists if not grass.find_file(raster)["file"]: grass.fatal(_("Raster map <%s> not found") % raster) if maskcats != "*" and not remove: if grass.raster_info(raster)["datatype"] != "CELL": grass.fatal( _( "The raster map <%s> must be integer (CELL type) " " in order to use the 'maskcats' parameter" ) % raster ) p = grass.feed_command("r.reclass", input=raster, output="MASK", overwrite=True, rules="-") p.stdin.write("%s = 1" % maskcats) p.stdin.close() p.wait() elif vector: vector_name = grass.find_file(vector, "vector")["fullname"] if not vector_name: grass.fatal(_("Vector map <%s> not found") % vector) # parser bug? if len(cats) == 0: cats = None if len(where) == 0: where = None if grass.vector_info_topo(vector_name)["areas"] < 1: grass.warning(_("No area found in vector map <%s>. " "Creating a convex hull for MASK.") % vector_name) global tmp_hull tmp_hull = "tmp_hull_%d" % os.getpid() to_rast_input = tmp_hull # force 'flat' convex hull for 3D vector maps if 0 != grass.run_command( "v.hull", flags="f", quiet=True, input=vector_name, output=tmp_hull, layer=layer, cats=cats, where=where, ): grass.fatal(_("Unable to create a convex hull for vector map <%s>") % vector_name) else: to_rast_input = vector_name env = os.environ.copy() if grass.verbosity() > 1: env["GRASS_VERBOSE"] = "1" grass.run_command( "v.to.rast", input=to_rast_input, layer=layer, output="MASK", use="val", val="1", type="area", cats=cats, where=where, env=env, ) if invert: global tmp tmp = "r_mask_%d" % os.getpid() grass.run_command("g.rename", rast=("MASK", tmp), quiet=True) grass.message(_("Creating inverted raster MASK...")) grass.mapcalc("MASK = if(isnull($tmp), 1, null())", tmp=tmp) grass.verbose(_("Inverted raster MASK created")) else: grass.verbose(_("Raster MASK created")) grass.message( _( "All subsequent raster operations will be limited to " "the MASK area. Removing or renaming raster map named " "'MASK' will restore raster operations to normal." ) )
def main(): ''' acces BDD PostGIS''' BDDNAME='saturne' IP='92.222.75.150' LOGIN='******' MDP='z9pY1Pm6dKaTuNfwMbSj' ''' importation ''' # .message("Importation du reseau RCU...") # SCHEM='topology' # COUCHE='linear' # sql="source = 'LIGNES_CONSTRUCTIBLES_2015_05_11' AND id NOT LIKE 'TRONROUT%'" # grass.run_command('v.in.ogr', input='PG:dbname=' + BDDNAME + ' host=' + IP + ' port=5432' + ' user='******' password='******' sslmode=require' + ' schemas=' + SCHEM, output='ORI_rsxRCU', where=sql, layer=COUCHE, quiet=True) # grass.message("Importation du reseau routier...") # SCHEM='topology' # COUCHE='linear' # sql="source = 'LIGNES_CONSTRUCTIBLES_2015_05_11' AND id LIKE 'TRONROUT%'" # grass.run_command('v.in.ogr', input='PG:dbname=' + BDDNAME + ' host=' + IP + ' port=5432' + ' user='******' password='******' sslmode=require' + ' schemas=' + SCHEM, output='ORI_rsxRTE', where=sql, layer=COUCHE, quiet=True) # ORI_enveloppebati - ne pas nettoyer la geometrie # grass.message("Importation des chaufferies...") # SCHEM='topology' # COUCHE='punctual' # sql="source = 'SAISIE_MANUELLE_DALKIA_FORCITY'" # grass.run_command('v.in.ogr', input='PG:dbname=' + BDDNAME + ' host=' + IP + ' port=5432' + ' user='******' password='******' sslmode=require' + ' schemas=' + SCHEM, output='ORI_Chauff', where=sql, layer=COUCHE, quiet=True) ''' Creation des couches finales ''' grass.message("Preparation des couches...") grass.run_command('g.copy', vector=('ORI_enveloppebati','TMPPP_bati'), quiet=True) #enveloppes bti ! # non utile a priori - grass.run_command('v.clean', flags='c', input="ORI_bati", output='TMPPP_bati_full', tool='break', quiet=True) # grass.run_command('v.clean', flags='c', input="ORI_rsxRCU", output='TMPPP_rsx_RCU', tool='break', quiet=True) # grass.run_command('v.clean', flags='c', input="ORI_rsxRTE", output='TMPPP_rsx_ROUTES', tool='break', quiet=True) grass.run_command('g.copy', vector=('ORI_Chauff','TMPP_Chauff'), quiet=True) ''' recuperation des distances ''' grass.message("calcul des distances...") grass.run_command('v.db.addcolumn', map='TMPP_Chauff', columns='BATIID varchar(254),RSXRCU DOUBLE PRECISION,RSXRTETP DOUBLE PRECISION,RSXRTE DOUBLE PRECISION,DISTBATI DOUBLE PRECISION', quiet=True) grass.read_command('v.distance', _from='TMPP_Chauff', from_type='point', to='TMPPP_bati', to_type='area', upload='to_attr', to_colum='id', column='BATIID', quiet=True) grass.read_command('v.distance', _from='TMPP_Chauff', from_type='point', to='TMPPP_bati', to_type='area', upload='dist', column='DISTBATI', quiet=True) grass.read_command('v.distance', _from='TMPP_Chauff', from_type='point', to='TMPPP_rsx_RCU', to_type='line', upload='dist', column='RSXRCU', quiet=True) grass.read_command('v.distance', _from='TMPP_Chauff', from_type='point', to='TMPPP_rsx_ROUTES', to_type='line', upload='dist', column='RSXRTETP', quiet=True) grass.run_command('v.db.update', map='TMPP_Chauff', column='RSXRTE', query_column='RSXRTETP+32', quiet=True) grass.run_command('v.db.dropcolumn', map='TMPP_Chauff', columns='RSXRTETP', quiet=True) ''' exctraction selon criteres ''' ListChauff=[] grass.message("extraction...") expr='RSXRCU<RSXRTE' grass.run_command('v.extract', input='TMPP_Chauff', output='ORI_Chauff_RCU', where=expr, quiet=True) grass.run_command('v.db.renamecolumn', map='ORI_Chauff_RCU', column=('RSXRCU','DISTRSX'), quiet=True) grass.run_command('v.db.dropcolumn', map='ORI_Chauff_RCU', columns='RSXRTE', quiet=True) infopt = grass.vector_info_topo('ORI_Chauff_RCU') if infopt['points'] > 0: ListChauff.append('ORI_Chauff_RCU') grass.run_command('v.extract', flags='r', input='TMPP_Chauff', output='ORI_Chauff_RTE', where=expr, quiet=True) grass.run_command('v.db.renamecolumn', map='ORI_Chauff_RTE', column=('RSXRTE','DISTRSX'), quiet=True) grass.run_command('v.db.dropcolumn', map='ORI_Chauff_RTE', columns='RSXRCU', quiet=True) infopt = grass.vector_info_topo('ORI_Chauff_RTE') if infopt['points'] > 0: ListChauff.append('ORI_Chauff_RTE') ''' verification des connections possibles ''' grass.message("finalisation...") for layer in ListChauff: expr='DISTBATI>DISTRSX' grass.run_command('v.extract', input=layer, output='TMPP_NetSimple_' + layer, where=expr, quiet=True) grass.run_command('v.extract', flags='r', input=layer, output='TMPPP_NetProcess_' + layer, where=expr, quiet=True) infopt = grass.vector_info_topo('TMPP_NetSimple_ORI_Chauff_RCU') if infopt['points'] > 0: grass.read_command('v.distance', flags='p', _from='TMPP_NetSimple_ORI_Chauff_RCU', from_type='point', to='TMPPP_rsx_RCU', to_type='line', upload='dist', output='TP_NetSimple_ORI_Chauff_CONNECT_RCU', quiet=True) grass.run_command('v.db.addtable', map='TP_NetSimple_ORI_Chauff_CONNECT_RCU', columns="source varchar(255), id varchar(255), valid_time varchar(255)", quiet=True) grass.run_command('v.db.update', map='TP_NetSimple_ORI_Chauff_CONNECT_RCU', column='source', value='RACCsimpleRCU_FORCITY', quiet=True) infopt = grass.vector_info_topo('TMPP_NetSimple_ORI_Chauff_RTE') if infopt['points'] > 0: grass.read_command('v.distance', flags='p', _from='TMPP_NetSimple_ORI_Chauff_RTE', from_type='point', to='TMPPP_rsx_ROUTES', to_type='line', upload='dist', output='TP_NetSimple_ORI_Chauff_CONNECT_RTE', quiet=True) grass.run_command('v.db.addtable', map='TP_NetSimple_ORI_Chauff_CONNECT_RTE', columns="source varchar(255), id varchar(255), valid_time varchar(255)", quiet=True) grass.run_command('v.db.update', map='TP_NetSimple_ORI_Chauff_CONNECT_RTE', column='source', value='RACCsimpleRTE_FORCITY', quiet=True) dvectNetSimple = grass.parse_command('g.list', type="vect", pattern="TP_NetSimple_ORI_Chauff_CONNECT_*", quiet=True) grass.run_command('v.edit', tool='create', map='TP_Raccord_NetSimple_Finale', quiet=True) grass.run_command('v.db.addtable', map='TP_Raccord_NetSimple_Finale', columns="source varchar(255), id varchar(255), valid_time varchar(255)", quiet=True) for vct in dvectNetSimple: grass.run_command('v.patch', flags='ea', input=vct, output='TP_Raccord_NetSimple_Finale', quiet=True, overwrite=True) grass.run_command('v.db.update', map='TP_Raccord_NetSimple_Finale', column='source', value='RACC_FORCITY', quiet=True) grass.run_command('v.db.update', map='TP_Raccord_NetSimple_Finale', column='id', value='RACC_DIRECT', quiet=True) tempfile = ['TMPP_*'] clean(tempfile) # ''' connection complexe ''' # ''' Creation de la couche finale ''' listerrorRCU=[] listerrorRTE=[] grass.message("Preparation des couches...") grass.run_command('v.patch', flags='e', input=('TMPPP_NetProcess_ORI_Chauff_RCU','TMPPP_NetProcess_ORI_Chauff_RTE'), output='TMPPP_NetProcess', quiet=True) grass.run_command('v.db.addcolumn', map='TMPPP_NetProcess', columns='NUM INTEGER', quiet=True) valuecat=grass.parse_command('v.category', input='TMPPP_NetProcess', type='point', option='print') newcat=1 for f in valuecat: grass.write_command("db.execute", input="-", stdin="update TMPPP_NetProcess SET NUM='{0}' WHERE cat='{1}'".format(newcat,str(f)), quiet=True) newcat+=1 grass.run_command('v.edit', tool='create', map='TP_Raccord_NetProcess_Finale', quiet=True) grass.run_command('v.db.addtable', map='TP_Raccord_NetProcess_Finale', columns="source varchar(255), id varchar(255), valid_time varchar(255)", quiet=True) infopt = grass.vector_info_topo('TMPPP_NetProcess') objpt = 1 while objpt <= infopt['points']: grass.message("\nPoint N. {0} / {1}" .format(objpt,infopt['points'])) grass.message("extraction des chaufferies...") expr='NUM='+str(objpt) grass.run_command('v.extract', input='TMPPP_NetProcess', output='TMP_NetProcess_pt'+str(objpt), where=expr, quiet=True) grass.message("extraction du batiment correspondant et retraitement...") catbati=grass.read_command('v.db.select', flags='cv', map='TMP_NetProcess_pt'+str(objpt), columns='BATIID', quiet=True) attbati=catbati.split()[0] expr="id='"+str(attbati)+"'" # grass.run_command('v.extract', input='TMPPP_bati', output='TMP_NetProcess_bati_extract'+str(objpt), where=expr, quiet=True) grass.run_command('v.extract', input='TMPPP_bati', output='TMP_NetProcess_bati_ext'+str(objpt), where=expr, quiet=True) grass.run_command('v.centroids', input='TMP_NetProcess_bati_ext'+str(objpt), output='TMP_NetProcess_bati_ext_centro'+str(objpt), quiet=True) grass.run_command('v.category', input='TMP_NetProcess_bati_ext_centro'+str(objpt), output='TMP_NetProcess_bati_ext_centro_catego'+str(objpt), option='add', quiet=True) grass.run_command('v.extract', flags='d', input='TMP_NetProcess_bati_ext_centro_catego'+str(objpt), output='TMP_NetProcess_bati_extract'+str(objpt), new='1', quiet=True) grass.message("extraction des coordonnees du batiment correspondant...") coordbati=grass.read_command('v.info', flags='g', map='TMP_NetProcess_bati_extract'+str(objpt), quiet=True) dictcoordbati= dict( (n,str(v)) for n,v in (a.split('=') for a in coordbati.split() ) ) grass.message("calcul de la distance du reseau le plus proche...") distrsxRTE = grass.read_command('v.distance', flags='p', _from='TMP_NetProcess_pt'+str(objpt), from_type='point', to='TMPPP_rsx_ROUTES', to_type='line', upload='dist', quiet=True) distancersxRTE=[] for i in distrsxRTE.split(): distancersxRTE.append(i.split('|')) distancersxRTE.remove(distancersxRTE[0]) distanceRTE = ceil(float(distancersxRTE[0][1])) distrsxRCU = grass.read_command('v.distance', flags='p', _from='TMP_NetProcess_pt'+str(objpt), from_type='point', to='TMPPP_rsx_RCU', to_type='line', upload='dist', quiet=True) distancersxRCU=[] for i in distrsxRCU.split(): distancersxRCU.append(i.split('|')) distancersxRCU.remove(distancersxRCU[0]) distanceRCU = ceil(float(distancersxRCU[0][1])) ''' On recherche la coordonnes la plus proche par rapport aux deux reseaux ; la valeur 10 est le decalage possible # CORRECTION +60m car les chauff loin des batiment sont pas pris en compte le reseau peux ne pas etre pris par l'overlay ensuite de la region calculee ci dessus... dou 60m.. ''' if (distanceRCU <= distanceRTE+32): distance = distanceRCU+32 else: distance = distanceRTE+32 grass.message("calage de la region sur l'emprise du batiment correspondant...") grass.run_command('g.region', flags='a', n=float(dictcoordbati['north'])+distance, s=float(dictcoordbati['south'])-distance, e=float(dictcoordbati['east'])+distance, w=float(dictcoordbati['west'])-distance, quiet=True) grass.run_command('v.in.region', output='TMP_NetProcess_region_L'+str(objpt), quiet=True) grass.message("extraction du reseau sur la region de travail...") if (distanceRCU <= distanceRTE+32): # RCU == 'ok': grass.message("RCU - conversion ligne du reseau vers point et calcul du cout...") grass.run_command('v.overlay', flags='t', ainput='TMPPP_rsx_RCU', atype='line', binput='TMP_NetProcess_region_L'+str(objpt), output='TMP_NetProcess_rsx_RCU'+str(objpt), operator='and', quiet=True) grass.run_command('v.to.points', input='TMP_NetProcess_rsx_RCU'+str(objpt), output='TMP_NetProcess_rsx_RCU_pt'+str(objpt), dmax='1', quiet=True) grass.run_command('g.copy', vector=('TMP_NetProcess_rsx_RCU_pt'+str(objpt),'TMP_NetProcess_rsx_pt'+str(objpt)), quiet=True) typeracc = 'RCU' else: grass.message("ROUTES - conversion ligne du reseau vers point et calcul du cout...") grass.run_command('v.overlay', flags='t', ainput='TMPPP_rsx_ROUTES', atype='line', binput='TMP_NetProcess_region_L'+str(objpt), output='TMP_NetProcess_rsx_ROUTES'+str(objpt), operator='and', quiet=True) grass.run_command('v.to.points', input='TMP_NetProcess_rsx_ROUTES'+str(objpt), output='TMP_NetProcess_rsx_ROUTES_pt'+str(objpt), dmax='1', quiet=True) grass.run_command('g.copy', vector=('TMP_NetProcess_rsx_ROUTES_pt'+str(objpt),'TMP_NetProcess_rsx_pt'+str(objpt)), quiet=True) typeracc = 'ROUTES' grass.message("assemblage des bati point et du reseau point pour un maillage de point complet...") grass.run_command('v.to.points', input='TMP_NetProcess_bati_extract'+str(objpt), output='TMP_NetProcess_region_bati_pt'+str(objpt), type='area', dmax='1', quiet=True) grass.run_command('v.patch', input=('TMP_NetProcess_region_bati_pt'+str(objpt),'TMP_NetProcess_rsx_pt'+str(objpt)), output='TMP_NetProcess_pt_bati_rsx'+str(objpt), quiet=True) grass.message("creation du diagramme de voronoi...") grass.run_command('v.voronoi', flags='l', input='TMP_NetProcess_pt_bati_rsx'+str(objpt), output='TMP_NetProcess_pt_bati_rsx_voro'+str(objpt), quiet=True) grass.message("suppression des lignes du voronoi a linterieur de chaque bati...") grass.run_command('v.overlay', flags='t', ainput='TMP_NetProcess_pt_bati_rsx_voro'+str(objpt), atype='line', binput='TMP_NetProcess_bati_extract'+str(objpt), output='TMP_NetProcess_voroNot_'+str(objpt), operator='not', quiet=True) grass.message("prise en compte des autres batiments...") grass.run_command('v.select', ainput='TMPPP_bati', atype='area', binput="TMP_NetProcess_region_L"+str(objpt), btype='area', output='TMP_NetProcess_bati_select'+str(objpt), operator='overlap', quiet=True) ''' grass.run_command('v.clean', flags='c', input="TMP_NetProcess_bati_select"+str(objpt), output='TMP_NetProcess_bati_select_cl'+str(objpt), tool='snap,break,bpol', type='boundary', threshold='1', quiet=True)''' '''fusion''' # verif grass.run_command('v.extract', flags='r', input='TMP_NetProcess_bati_select'+str(objpt), output='TMP_NetProcess_bati_select_cl_buff_fusio'+str(objpt), where=expr, quiet=True) # grass.run_command('v.extract', flags='d', input='TMP_NetProcess_bati_select_cl_buff_ext'+str(objpt), output='TMP_NetProcess_bati_select_cl_buff_fusio'+str(objpt), new='1', quiet=True) grass.message("suppression graph voro dans autre bati...") grass.run_command('v.overlay', flags='t', ainput='TMP_NetProcess_voroNot_'+str(objpt), atype='line', binput='TMP_NetProcess_bati_select_cl_buff_fusio'+str(objpt), output='TMP_NetProcess_voroNot_bis'+str(objpt), operator='not', quiet=True) grass.message("conversion du bati en ligne avec voro pour integration dans la couche voronoi et nettoyage...") grass.run_command('v.type', input='TMP_NetProcess_bati_extract'+str(objpt), output='TMP_NetProcess_region_bati_buff_line'+str(objpt), from_type='boundary', to_type='line', quiet=True) ''' integration des autres bati ''' grass.run_command('v.type', input='TMP_NetProcess_bati_select_cl_buff_fusio'+str(objpt), output='TMP_NetProcess_bati_select_cl_buff_line'+str(objpt), from_type='boundary', to_type='line', quiet=True) ''' on ne veux pas des lignes a linterieur du polygone du bati retrace - idem raccord enfin uniquement dans les bati.. ''' #useless grass.run_command('v.overlay', flags='t', ainput='TMP_NetProcess_bati_select_cl_buff_line'+str(objpt), atype='line', binput='TMP_NetProcess_bati_extract'+str(objpt), output='TMP_NetProcess_bati_select_cl_buff_line_not'+str(objpt), operator='not', quiet=True) ''' integration des raccords existants... ''' inforacc = grass.vector_info_topo('TP_Raccord_NetProcess_Finale') if inforacc['lines'] == 0: grass.run_command('v.patch', input=('TMP_NetProcess_voroNot_bis'+str(objpt),'TMP_NetProcess_region_bati_buff_line'+str(objpt),'TMP_NetProcess_bati_select_cl_buff_line_not'+str(objpt)), output='TMP_NetProcess_voroNot_bati_line'+str(objpt), quiet=True) else: grass.run_command('v.extract', input='TP_Raccord_NetProcess_Finale', type='line', output='TMP_NetProcess_Raccord'+str(objpt), quiet=True) grass.run_command('v.patch', input=('TMP_NetProcess_voroNot_bis'+str(objpt),'TMP_NetProcess_region_bati_buff_line'+str(objpt),'TMP_NetProcess_Raccord'+str(objpt),'TMP_NetProcess_bati_select_cl_buff_line_not'+str(objpt)), output='TMP_NetProcess_voroNot_bati_line'+str(objpt), quiet=True) grass.run_command('v.clean', flags='c', input="TMP_NetProcess_voroNot_bati_line"+str(objpt), output='TMP_NetProcess_voroNot_bati_line_cl'+str(objpt), tool='snap,break', type='area', threshold='0.1', quiet=True) ''' connection avec le bati et les chaufferie ''' grass.message("generation du 1er reseau...") grass.run_command('v.net', flags='c', input='TMP_NetProcess_voroNot_bati_line_cl'+str(objpt), points='TMP_NetProcess_pt'+str(objpt), output='TMP_NetProcess_voroNot_bati_line_cl_PT_cnct_'+str(objpt), operation='connect', threshold='10000', quiet=True) grass.run_command('v.clean', flags='c', input="TMP_NetProcess_voroNot_bati_line_cl_PT_cnct_"+str(objpt), output='TMP_NetProcess_voroNot_bati_line_cl_PT_cnct_cl'+str(objpt), tool='break', quiet=True) ''' connection avec le bati + raccord chaufferie ET le reseau en PT ''' grass.message("generation du 2nd reseau...") grass.run_command('v.net', flags='c', input='TMP_NetProcess_voroNot_bati_line_cl_PT_cnct_cl'+str(objpt), points='TMP_NetProcess_rsx_pt'+str(objpt), output='TMP_NetProcess_voroNot_bati_line_cl_PT_cnct_cl_rsx_cnct'+str(objpt), operation='connect', node_layer='3', threshold='10000', quiet=True) ''' nettoyage du reseau ''' grass.message("nettoyage du reseau...") grass.run_command('v.clean', flags='c', input="TMP_NetProcess_voroNot_bati_line_cl_PT_cnct_cl_rsx_cnct"+str(objpt), output='TMP_NetProcess_voroNot_bati_line_cl_PT_cnct_cl_rsx_cnct_cl'+str(objpt), tool='snap,break', threshold='0.1', quiet=True) ''' calcul du chemin le plus court ''' grass.message("Calcul du chemin le plus court...") # a priori pas besoin de cout pour ligne.. grass.run_command('v.net.distance', input='TMP_NetProcess_voroNot_bati_line_cl_PT_cnct_cl_rsx_cnct_cl'+str(objpt), output='TMP_NetProcess_'+str(objpt), from_layer='2', to_layer='3', quiet=True) ''' remplissage des attributs ''' grass.message("Remplissage des attributs...") grass.run_command('v.db.droptable', flags ='f', map='TMP_NetProcess_'+str(objpt), quiet=True) grass.run_command('v.db.addtable', map='TMP_NetProcess_'+str(objpt), columns="source varchar(255), id varchar(255), valid_time varchar(255)", quiet=True) grass.run_command('v.db.update', map='TMP_NetProcess_'+str(objpt), column='source', value='RACC_FORCITY'+str(objpt), quiet=True) grass.run_command('v.db.update', map='TMP_NetProcess_'+str(objpt), column='id', value='RACC_OK_'+ typeracc, quiet=True) ''' grass.run_command('v.clean', flags='c', input='TP_Raccord_NetProcess_Finale', output='TP_Raccord_NetProcess_Finale_clean', tool='break,snap,chbridge,rmsa', threshold='0,0.5', quiet=True) # grass.run_command('v.clean', flags='c', input='Raccord_prune2', output='Raccord_final10', tool='break,snap,chbridge,rmsa', threshold='0,0.5', quiet=True) ''' grass.run_command('v.patch', flags='ea', input='TMP_NetProcess_'+str(objpt), output='TP_Raccord_NetProcess_Finale', quiet=True, overwrite=True) infoPB = grass.vector_info_topo('TMP_NetProcess_'+str(objpt)) if infoPB['lines'] == 0: if typeracc == 'RCU': listerrorRCU.append(str(objpt)) elif typeracc == 'ROUTES': listerrorRTE.append(str(objpt)) grass.message("problemes : {0}".format(listerrorRCU)) grass.message("problemes : {0}".format(listerrorRTE)) ''' Nettoyage fichier temporaires ''' tempfile = ['TMP_*'] clean(tempfile) objpt+=1 ''' traitement des chaufferies posant problemes''' grass.message("traitements des erreurs") op = ' OR ' if listerrorRCU: errorRCU=[] for f in listerrorRCU: expr='NUM='+str(f) errorRCU.append(expr + op) grass.run_command('v.extract', input='TMPPP_NetProcess', output='TMPPP_NetProcess_PB_RCU', where=''.join(errorRCU)[:-4], quiet=True) grass.read_command('v.distance', flags='p', _from='TMPPP_NetProcess_PB_RCU', from_type='point', to='TMPPP_rsx_RCU', to_type='line', upload='dist', output='TP_NetProcess_PB_CONNECT_RCU', quiet=True) grass.run_command('v.db.addtable', map='TP_NetProcess_PB_CONNECT_RCU', columns="source varchar(255), id varchar(255), valid_time varchar(255)", quiet=True) grass.run_command('v.db.update', map='TP_NetProcess_PB_CONNECT_RCU', column='source', value='RACC_FORCITY', quiet=True) grass.run_command('v.db.update', map='TP_NetProcess_PB_CONNECT_RCU', column='id', value='RACC_RCU_AREVOIR', quiet=True) if listerrorRTE: errorRTE=[] for f in listerrorRTE: expr='NUM='+str(f) errorRTE.append(expr + op) grass.run_command('v.extract', input='TMPPP_NetProcess', output='TMPPP_NetProcess_PB_RTE', where=''.join(errorRTE)[:-4], quiet=True) grass.read_command('v.distance', flags='p', _from='TMPPP_NetProcess_PB_RTE', from_type='point', to='TMPPP_rsx_ROUTES', to_type='line', upload='dist', output='TP_NetProcess_PB_CONNECT_RTE', quiet=True) grass.run_command('v.db.addtable', map='TP_NetProcess_PB_CONNECT_RTE', columns="source varchar(255), id varchar(255), valid_time varchar(255)", quiet=True) grass.run_command('v.db.update', map='TP_NetProcess_PB_CONNECT_RTE', column='source', value='RACC_FORCITY', quiet=True) grass.run_command('v.db.update', map='TP_NetProcess_PB_CONNECT_RTE', column='id', value='RACC_RTE_AREVOIR', quiet=True) vectraccordPB = grass.parse_command('g.list', type="vect", pattern="TP_NetProcess_PB_CONNECT_*", quiet=True) grass.run_command('v.edit', tool='create', map='TP_Raccord_NetPB_Finale', quiet=True) grass.run_command('v.db.addtable', map='TP_Raccord_NetPB_Finale', columns="source varchar(255), id varchar(255), valid_time varchar(255)", quiet=True) for vect in vectraccordPB: grass.run_command('v.patch', flags='ea', input=vect, output='TP_Raccord_NetPB_Finale', quiet=True, overwrite=True) ''' assemblage des raccords dans une seule couche ''' vectraccordFIN = grass.parse_command('g.list', type="vect", pattern="TP_Raccord_Net*", quiet=True) grass.run_command('v.edit', tool='create', map='TP_Raccord_Finale', quiet=True) grass.run_command('v.db.addtable', map='TP_Raccord_Finale', columns="source varchar(255), id varchar(255), valid_time varchar(255)", quiet=True) for vect in vectraccordFIN: grass.run_command('v.patch', flags='ea', input=vect, output='TP_Raccord_Finale', quiet=True, overwrite=True) ''' posttraitement des raccords ''' grass.run_command('v.net', input='TP_Raccord_Finale', points='TMPP_Chauff', output='TP_Raccord_Finale_connect', operation='connect', thresh='0.1', quiet=True) grass.run_command('v.clean', input='TP_Raccord_Finale_connect', output='TP_Raccord_Finale_connect_clean', tool='break,snap', thresh='0,0.1', quiet=True) grass.run_command('v.generalize', flags='c', input='TP_Raccord_Finale_connect_clean', output='TP_Raccord_Finale_connect_clean_gene', method='lang', threshold='1', quiet=True) grass.run_command('v.clean', input='TP_Raccord_Finale_connect_clean_gene', output='TP_Raccord_Finale_connect_clean_gene_clean', tool='break,snap,rmdangle', thresh='0,0.1', quiet=True) grass.run_command('v.db.dropcolumn', map='TP_Raccord_Finale_connect_clean_gene_clean', columns='cat_', quiet=True) grass.run_command('v.patch', flags='ea', input=('TMPPP_rsx_RCU','TMPPP_rsx_ROUTES'), output='TP_Reseau', quiet=True, overwrite=True) grass.run_command('v.patch', input=('TP_Raccord_Finale_connect_clean_gene_clean','TP_Reseau'), output='TP_Reseau_RCU_complet', quiet=True) grass.run_command('v.clean', input='TP_Reseau_RCU_complet', output='Reseau_raccord', type='point,line', tool='snap,break,rmdangle,rmdupl,rmsa', thresh='0.1', quiet=True) ''' export postgis ''' SCHEM='public' grass.run_command('v.out.ogr', input='Reseau_raccord', type='line', output='PG:dbname=' + BDDNAME + ' host=' + IP + ' port=5432' + ' user='******' password='******' sslmode=require' + ' schemas=' + SCHEM, output_layer='Reseau_raccord', format='PostgreSQL') return 0
def main(): global tmp, nuldev nuldev = file(os.devnull, 'w') ## setup temporary files tmp = grass.tempfile() tmpf = 'v_net_neighbors' inmap = options['input'] outfile = options['dump'] # check if input file exists if not grass.find_file(inmap, element = 'vector')['file']: grass.fatal(_("<%s> does not exist.") % inmap) # check for table in net vector map try: f = grass.vector_db(inmap)[2] except KeyError: grass.run_command('v.db.addtable', _map = inmap, layer = 2, quiet = True, stderr = nuldev) ## extract temp nodes and lines nodes = tmpf + '_nodes' lines = tmpf + '_lines' iflines = grass.vector_info_topo(inmap)['lines'] ifbounds = grass.vector_info_topo(inmap)['boundaries'] if iflines != 0: vect_type = 'line' if ifbounds != 0: vect_type = 'boundary' if iflines != 0 and ifbounds != 0: grass.fatal(_("Input net vector map must have lines OR boundaries, not both")) grass.run_command('v.extract', input = inmap, output = nodes, layer = 2, _type = 'point', flags = 't', quiet = True, stderr = nuldev) grass.run_command('v.extract', input = inmap, output = lines, _type = vect_type, flags = 't', quiet = True, stderr = nuldev) ## filter nodes on line intersections if with '-i' flag if flags['i']: p = grass.pipe_command('v.net', _input = inmap, operation = 'nreport', quiet = True, stderr = nuldev) c = p.communicate()[0].strip().split('\n') filt = [elem for elem in c if ',' in elem] fnodes = [] for x in filt: spl = x.split(' ') fnodes.append(spl[0]) fnodes_str = ','.join(fnodes) nsel = tmpf + '_nsel' grass.run_command('v.extract', _input = nodes, _list = fnodes_str, output = nsel, layer = 2, _type = 'point', quiet = True, stderr = nuldev) grass.run_command('g.rename', vect = (nsel,nodes), overwrite = True, quiet = True, stderr = nuldev) if not flags['p']: grass.run_command('v.db.addcol', _map = inmap, layer = 2, columns = 'neigh_node varchar(255)', quiet = True, stderr = nuldev) ## main cycle (extract every node and make 2 selects) out_dict = {} p = grass.pipe_command('v.category', _input = nodes, opt = 'print', layer = 2, _type = 'point', quiet = True, stderr = nuldev) c = p.communicate()[0].strip().split('\n') for cat in c: icat = int(cat) nnode = nodes + cat grass.run_command('v.extract', _input = nodes, _list = cat, output = nnode, layer = 2, _type = 'point', flags = 't', quiet = True, stderr = nuldev) linode = nnode + '_lines' grass.run_command('v.select', ain = lines, _bin = nnode, blayer = 2, output = linode, operator = 'overlap', quiet = True, stderr = nuldev) linode_pts = linode + '_pts' grass.run_command('v.select', ain = nodes, alayer = 2, _bin = linode, output = linode_pts, operator = 'overlap', quiet = True, stderr = nuldev) pcat = grass.pipe_command('v.category', _input = linode_pts, layer = 2, opt = 'print', quiet = True, stderr = nuldev) ccat = pcat.communicate()[0].strip().split('\n') ccat.remove(cat) ncat_list = [] ncat_list.append(ccat) str_db = ','.join(map(str, ncat_list)) str_db1 = str_db.replace("[", "").replace("]", "").replace("'", "").replace(" ", "") out_dict[icat] = str_db1 if not flags['p']: grass.run_command('v.db.update', _map = inmap, layer = 2, column = 'neigh_node', value = '%s' % (str_db1), where = "cat = %d" % (icat), quiet = True, stderr = nuldev ) ## output to stdout / file tmp3 = tmp + '.out' outf2 = file(tmp3, 'w') for key in sorted(out_dict.iterkeys()): val = out_dict[key] print >> outf2, "%s %s" % (key,val) outf2.close() if flags['p']: with open(tmp3, 'rb') as f: print f.read() if outfile: shutil.copyfile(tmp3, outfile) return 0
def main(): input = options["input"] if options["refline"]: refline_cat = int(options["refline"]) else: refline_cat = None nb_vertices = int(options["vertices"]) if options["range"]: search_range = float(options["range"]) else: search_range = None output = options["output"] transversals = flags["t"] median = flags["m"] global tmp_points_map global tmp_centerpoints_map global tmp_line_map global tmp_cleaned_map global tmp_map tmp_points_map = "points_map_tmp_%d" % os.getpid() tmp_centerpoints_map = "centerpoints_map_tmp_%d" % os.getpid() tmp_line_map = "line_map_tmp_%d" % os.getpid() tmp_cleaned_map = "cleaned_map_tmp_%d" % os.getpid() tmp_map = "generaluse_map_tmp_%d" % os.getpid() nb_lines = grass.vector_info_topo(input)["lines"] # Find best reference line and max distance between centerpoints of lines segment_input = "" categories = grass.read_command("v.category", input=input, option="print", quiet=True).splitlines() for category in categories: segment_input += "P {}".format(category.strip()) segment_input += " {} {}".format(category.strip(), " 50%") segment_input += os.linesep grass.write_command( "v.segment", input=input, output=tmp_centerpoints_map, rules="-", stdin=segment_input, quiet=True, ) center_distances = grass.read_command( "v.distance", from_=tmp_centerpoints_map, to=tmp_centerpoints_map, upload="dist", flags="pa", quiet=True, ).splitlines() cats = [] mean_dists = [] count = 0 distmax = 0 for center in center_distances: if count < 2: count += 1 continue cat = center.strip().split("|")[0] distsum = 0 for x in center.strip().split("|")[1:]: distsum += float(x) mean_dist = distsum / len(center.strip().split("|")[1:]) cats.append(cat) mean_dists.append(mean_dist) if transversals and not search_range: search_range = sum(mean_dists) / len(mean_dists) grass.message(_("Calculated search range: %.5f." % search_range)) if not refline_cat: refline_cat = sorted(zip(cats, mean_dists), key=lambda tup: tup[1])[0][0] grass.message( _("Category number of chosen reference line: %s." % refline_cat)) # Use transversals algorithm if transversals: # Break any intersections in the original lines so that # they do not interfere further on grass.run_command("v.clean", input=input, output=tmp_cleaned_map, tool="break", quiet=True) xmean = [] ymean = [] xmedian = [] ymedian = [] step = 100.0 / nb_vertices os.environ["GRASS_VERBOSE"] = "-1" for vertice in range(0, nb_vertices + 1): # v.segment sometimes cannot find points when # using 0% or 100% offset length_offset = step * vertice if length_offset < 0.00001: length_offset = 0.00001 if length_offset > 99.99999: length_offset = 99.9999 # Create endpoints of transversal segment_input = "P 1 %s %.5f%% %f\n" % ( refline_cat, length_offset, search_range, ) segment_input += "P 2 %s %.5f%% %f\n" % ( refline_cat, length_offset, -search_range, ) grass.write_command( "v.segment", input=input, output=tmp_points_map, stdin=segment_input, overwrite=True, ) # Create transversal grass.write_command( "v.net", points=tmp_points_map, output=tmp_line_map, operation="arcs", file="-", stdin="99999 1 2", overwrite=True, ) # Patch transversal onto cleaned input lines maps = tmp_cleaned_map + "," + tmp_line_map grass.run_command("v.patch", input=maps, out=tmp_map, overwrite=True) # Find intersections grass.run_command( "v.clean", input=tmp_map, out=tmp_line_map, tool="break", error=tmp_points_map, overwrite=True, ) # Add categories to intersection points grass.run_command( "v.category", input=tmp_points_map, out=tmp_map, op="add", overwrite=True, ) # Get coordinates of points coords = grass.read_command("v.to.db", map=tmp_map, op="coor", flags="p").splitlines() count = 0 x = [] y = [] for coord in coords: x.append(float(coord.strip().split("|")[1])) y.append(float(coord.strip().split("|")[2])) # Calculate mean and median for this transversal if len(x) > 0: xmean.append(sum(x) / len(x)) ymean.append(sum(y) / len(y)) x.sort() y.sort() xmedian.append((x[(len(x) - 1) // 2] + x[(len(x)) // 2]) / 2) ymedian.append((y[(len(y) - 1) // 2] + y[(len(y)) // 2]) / 2) del os.environ["GRASS_VERBOSE"] # Use closest point algorithm else: # Get reference line calculate its length grass.run_command("v.extract", input=input, output=tmp_line_map, cats=refline_cat, quiet=True) os.environ["GRASS_VERBOSE"] = "0" lpipe = grass.read_command("v.to.db", map=tmp_line_map, op="length", flags="p").splitlines() del os.environ["GRASS_VERBOSE"] for l in lpipe: linelength = float(l.strip().split("|")[1]) step = linelength / nb_vertices # Create reference points for vertice calculation grass.run_command( "v.to.points", input=tmp_line_map, output=tmp_points_map, dmax=step, quiet=True, ) nb_points = grass.vector_info_topo(tmp_points_map)["points"] cat = [] x = [] y = [] # Get coordinates of closest points on all input lines if search_range: points = grass.read_command( "v.distance", from_=tmp_points_map, from_layer=2, to=input, upload="to_x,to_y", dmax=search_range, flags="pa", quiet=True, ).splitlines() else: points = grass.read_command( "v.distance", from_=tmp_points_map, from_layer=2, to=input, upload="to_x,to_y", flags="pa", quiet=True, ).splitlines() firstline = True for point in points: if firstline: firstline = False continue cat.append((int(point.strip().split("|")[0]))) x.append(float(point.strip().split("|")[2])) y.append(float(point.strip().split("|")[3])) # Calculate mean coordinates xsum = [0] * nb_points ysum = [0] * nb_points linecount = [0] * nb_points for i in range(len(cat)): index = cat[i] - 1 linecount[index] += 1 xsum[index] = xsum[index] + x[i] ysum[index] = ysum[index] + y[i] xmean = [0] * nb_points ymean = [0] * nb_points for c in range(0, nb_points): xmean[c] = xsum[c] / linecount[c] ymean[c] = ysum[c] / linecount[c] # Calculate the median xmedian = [0] * nb_points ymedian = [0] * nb_points for c in range(0, nb_points): xtemp = [] ytemp = [] for i in range(len(cat)): if cat[i] == c + 1: xtemp.append(x[i]) ytemp.append(y[i]) xtemp.sort() ytemp.sort() xmedian[c] = (xtemp[(len(xtemp) - 1) // 2] + xtemp[(len(xtemp)) // 2]) / 2 ymedian[c] = (ytemp[(len(ytemp) - 1) // 2] + ytemp[(len(ytemp)) // 2]) / 2 # Create new line and write to file if median and nb_lines > 2: line = geo.Line(list(zip(xmedian, ymedian))) else: if median and nb_lines <= 2: grass.message( _("More than 2 lines necesary for median, using mean.")) line = geo.Line(list(zip(xmean, ymean))) new = VectorTopo(output) new.open("w") new.write(line) new.close()
def main(): input = options['input'] if options['refline']: refline_cat = int(options['refline']) else: refline_cat = None nb_vertices = int(options['vertices']) if options['range']: search_range = float(options['range']) else: search_range = None output = options['output'] transversals = flags['t'] median = flags['m'] global tmp_points_map global tmp_centerpoints_map global tmp_line_map global tmp_cleaned_map global tmp_map tmp_points_map = 'points_map_tmp_%d' % os.getpid() tmp_centerpoints_map = 'centerpoints_map_tmp_%d' % os.getpid() tmp_line_map = 'line_map_tmp_%d' % os.getpid() tmp_cleaned_map = 'cleaned_map_tmp_%d' % os.getpid() tmp_map = 'generaluse_map_tmp_%d' % os.getpid() nb_lines = grass.vector_info_topo(input)['lines'] # Find best reference line and max distance between centerpoints of lines segment_input = '' categories = grass.pipe_command('v.category', input=input, option='print', quiet=True) for category in categories.stdout: segment_input += 'P ' + category.strip() segment_input += ' ' + category.strip() + ' 50%\n' grass.write_command('v.segment', input=input, output=tmp_centerpoints_map, rules='-', stdin=segment_input, quiet=True) center_distances = grass.pipe_command('v.distance', from_=tmp_centerpoints_map, to=tmp_centerpoints_map, upload='dist', flags='pa', quiet=True) cats = [] mean_dists = [] count = 0 distmax = 0 for center in center_distances.stdout: if count < 2: count += 1 continue cat = center.strip().split('|')[0] distsum = 0 for x in center.strip().split('|')[1:]: distsum += float(x) mean_dist = distsum / len(center.strip().split('|')[1:]) cats.append(cat) mean_dists.append(mean_dist) if transversals and not search_range: search_range = sum(mean_dists) / len(mean_dists) grass.message(_("Calculated search range: %.5f." % search_range)) if not refline_cat: refline_cat = sorted(zip(cats, mean_dists), key=lambda tup: tup[1])[0][0] grass.message( _("Category number of chosen reference line: %s." % refline_cat)) # Use transversals algorithm if transversals: # Break any intersections in the original lines so that # they do not interfere further on grass.run_command('v.clean', input=input, output=tmp_cleaned_map, tool='break', quiet=True) xmean = [] ymean = [] xmedian = [] ymedian = [] step = 100.0 / nb_vertices os.environ['GRASS_VERBOSE'] = '-1' for vertice in range(0, nb_vertices + 1): # v.segment sometimes cannot find points when # using 0% or 100% offset length_offset = step * vertice if length_offset < 0.00001: length_offset = 0.00001 if length_offset > 99.99999: length_offset = 99.9999 # Create endpoints of transversal segment_input = 'P 1 %s %.5f%% %f\n' % (refline_cat, length_offset, search_range) segment_input += 'P 2 %s %.5f%% %f\n' % ( refline_cat, length_offset, -search_range) grass.write_command('v.segment', input=input, output=tmp_points_map, stdin=segment_input, overwrite=True) # Create transversal grass.write_command('v.net', points=tmp_points_map, output=tmp_line_map, operation='arcs', file='-', stdin='99999 1 2', overwrite=True) # Patch transversal onto cleaned input lines maps = tmp_cleaned_map + ',' + tmp_line_map grass.run_command('v.patch', input=maps, out=tmp_map, overwrite=True) # Find intersections grass.run_command('v.clean', input=tmp_map, out=tmp_line_map, tool='break', error=tmp_points_map, overwrite=True) # Add categories to intersection points grass.run_command('v.category', input=tmp_points_map, out=tmp_map, op='add', overwrite=True) # Get coordinates of points coords = grass.pipe_command('v.to.db', map=tmp_map, op='coor', flags='p') count = 0 x = [] y = [] for coord in coords.stdout: x.append(float(coord.strip().split('|')[1])) y.append(float(coord.strip().split('|')[2])) # Calculate mean and median for this transversal if len(x) > 0: xmean.append(sum(x) / len(x)) ymean.append(sum(y) / len(y)) x.sort() y.sort() xmedian.append((x[(len(x) - 1) / 2] + x[(len(x)) / 2]) / 2) ymedian.append((y[(len(y) - 1) / 2] + y[(len(y)) / 2]) / 2) del os.environ['GRASS_VERBOSE'] # Use closest point algorithm else: # Get reference line calculate its length grass.run_command('v.extract', input=input, output=tmp_line_map, cats=refline_cat, quiet=True) os.environ['GRASS_VERBOSE'] = '0' lpipe = grass.pipe_command('v.to.db', map=tmp_line_map, op='length', flags='p') del os.environ['GRASS_VERBOSE'] for l in lpipe.stdout: linelength = float(l.strip().split('|')[1]) step = linelength / nb_vertices # Create reference points for vertice calculation grass.run_command('v.to.points', input=tmp_line_map, output=tmp_points_map, dmax=step, quiet=True) nb_points = grass.vector_info_topo(tmp_points_map)['points'] cat = [] x = [] y = [] # Get coordinates of closest points on all input lines if search_range: points = grass.pipe_command('v.distance', from_=tmp_points_map, from_layer=2, to=input, upload='to_x,to_y', dmax=search_range, flags='pa', quiet=True) else: points = grass.pipe_command('v.distance', from_=tmp_points_map, from_layer=2, to=input, upload='to_x,to_y', flags='pa', quiet=True) firstline = True for point in points.stdout: if firstline: firstline = False continue cat.append((int(point.strip().split('|')[0]))) x.append(float(point.strip().split('|')[2])) y.append(float(point.strip().split('|')[3])) # Calculate mean coordinates xsum = [0] * nb_points ysum = [0] * nb_points linecount = [0] * nb_points for i in range(len(cat)): index = cat[i] - 1 linecount[index] += 1 xsum[index] = xsum[index] + x[i] ysum[index] = ysum[index] + y[i] xmean = [0] * nb_points ymean = [0] * nb_points for c in range(0, nb_points): xmean[c] = xsum[c] / linecount[c] ymean[c] = ysum[c] / linecount[c] # Calculate the median xmedian = [0] * nb_points ymedian = [0] * nb_points for c in range(0, nb_points): xtemp = [] ytemp = [] for i in range(len(cat)): if cat[i] == c + 1: xtemp.append(x[i]) ytemp.append(y[i]) xtemp.sort() ytemp.sort() xmedian[c] = (xtemp[(len(xtemp) - 1) / 2] + xtemp[(len(xtemp)) / 2]) / 2 ymedian[c] = (ytemp[(len(ytemp) - 1) / 2] + ytemp[(len(ytemp)) / 2]) / 2 # Create new line and write to file if median and nb_lines > 2: line = geo.Line(zip(xmedian, ymedian)) else: if median and nb_lines <= 2: grass.message( _("More than 2 lines necesary for median, using mean.")) line = geo.Line(zip(xmean, ymean)) new = VectorTopo(output) new.open('w') new.write(line) new.close()
def main(): global TMPLOC, SRCGISRC, GISDBASE, TMP_REG_NAME GDALdatasource = options["input"] output = options["output"] method = options["resample"] memory = options["memory"] bands = options["band"] tgtres = options["resolution"] title = options["title"] if flags["e"] and not output: output = "rimport_tmp" # will be removed with the entire tmp location if options["resolution_value"]: if tgtres != "value": grass.fatal( _("To set custom resolution value, select 'value' in resolution option" )) tgtres_value = float(options["resolution_value"]) if tgtres_value <= 0: grass.fatal(_("Resolution value can't be smaller than 0")) elif tgtres == "value": grass.fatal( _("Please provide the resolution for the imported dataset or change to 'estimated' resolution" )) # try r.in.gdal directly first additional_flags = "l" if flags["l"] else "" if flags["o"]: additional_flags += "o" region_flag = "" if options["extent"] == "region": region_flag += "r" if flags["o"] or is_projection_matching(GDALdatasource): parameters = dict( input=GDALdatasource, output=output, memory=memory, flags="ak" + additional_flags + region_flag, ) if bands: parameters["band"] = bands try: grass.run_command("r.in.gdal", **parameters) grass.verbose( _("Input <%s> successfully imported without reprojection") % GDALdatasource) return 0 except CalledModuleError: grass.fatal( _("Unable to import GDAL dataset <%s>") % GDALdatasource) grassenv = grass.gisenv() tgtloc = grassenv["LOCATION_NAME"] # make sure target is not xy if grass.parse_command("g.proj", flags="g")["name"] == "xy_location_unprojected": grass.fatal( _("Coordinate reference system not available for current location <%s>" ) % tgtloc) tgtmapset = grassenv["MAPSET"] GISDBASE = grassenv["GISDBASE"] TMPLOC = grass.append_node_pid("tmp_r_import_location") TMP_REG_NAME = grass.append_node_pid("tmp_r_import_region") SRCGISRC, src_env = grass.create_environment(GISDBASE, TMPLOC, "PERMANENT") # create temp location from input without import grass.verbose( _("Creating temporary location for <%s>...") % GDALdatasource) # creating a new location with r.in.gdal requires a sanitized env env = os.environ.copy() env = grass.sanitize_mapset_environment(env) parameters = dict( input=GDALdatasource, output=output, memory=memory, flags="c", title=title, location=TMPLOC, quiet=True, ) if bands: parameters["band"] = bands try: grass.run_command("r.in.gdal", env=env, **parameters) except CalledModuleError: grass.fatal(_("Unable to read GDAL dataset <%s>") % GDALdatasource) # prepare to set region in temp location if "r" in region_flag: tgtregion = TMP_REG_NAME grass.run_command("v.in.region", output=tgtregion, flags="d") # switch to temp location # print projection at verbose level grass.verbose( grass.read_command("g.proj", flags="p", env=src_env).rstrip(os.linesep)) # make sure input is not xy if (grass.parse_command("g.proj", flags="g", env=src_env)["name"] == "xy_location_unprojected"): grass.fatal( _("Coordinate reference system not available for input <%s>") % GDALdatasource) # import into temp location grass.verbose( _("Importing <%s> to temporary location...") % GDALdatasource) parameters = dict( input=GDALdatasource, output=output, memory=memory, flags="ak" + additional_flags, ) if bands: parameters["band"] = bands if "r" in region_flag: grass.run_command( "v.proj", location=tgtloc, mapset=tgtmapset, input=tgtregion, output=tgtregion, env=src_env, ) grass.run_command("g.region", vector=tgtregion, env=src_env) parameters["flags"] = parameters["flags"] + region_flag try: grass.run_command("r.in.gdal", env=src_env, **parameters) except CalledModuleError: grass.fatal(_("Unable to import GDAL dataset <%s>") % GDALdatasource) outfiles = grass.list_grouped("raster", env=src_env)["PERMANENT"] # is output a group? group = False path = os.path.join(GISDBASE, TMPLOC, "group", output) if os.path.exists(path): group = True path = os.path.join(GISDBASE, TMPLOC, "group", output, "POINTS") if os.path.exists(path): grass.fatal(_("Input contains GCPs, rectification is required")) if "r" in region_flag: grass.run_command("g.remove", type="vector", flags="f", name=tgtregion, env=src_env) # switch to target location if "r" in region_flag: grass.run_command("g.remove", type="vector", flags="f", name=tgtregion) region = grass.region() rflags = None if flags["n"]: rflags = "n" vreg = TMP_REG_NAME for outfile in outfiles: n = region["n"] s = region["s"] e = region["e"] w = region["w"] env = os.environ.copy() if options["extent"] == "input": # r.proj -g try: tgtextents = grass.read_command( "r.proj", location=TMPLOC, mapset="PERMANENT", input=outfile, flags="g", memory=memory, quiet=True, ) except CalledModuleError: grass.fatal(_("Unable to get reprojected map extent")) try: srcregion = grass.parse_key_val(tgtextents, val_type=float, vsep=" ") n = srcregion["n"] s = srcregion["s"] e = srcregion["e"] w = srcregion["w"] except ValueError: # import into latlong, expect 53:39:06.894826N srcregion = grass.parse_key_val(tgtextents, vsep=" ") n = grass.float_or_dms(srcregion["n"][:-1]) * ( -1 if srcregion["n"][-1] == "S" else 1) s = grass.float_or_dms(srcregion["s"][:-1]) * ( -1 if srcregion["s"][-1] == "S" else 1) e = grass.float_or_dms(srcregion["e"][:-1]) * ( -1 if srcregion["e"][-1] == "W" else 1) w = grass.float_or_dms(srcregion["w"][:-1]) * ( -1 if srcregion["w"][-1] == "W" else 1) env["GRASS_REGION"] = grass.region_env(n=n, s=s, e=e, w=w) # v.in.region in tgt grass.run_command("v.in.region", output=vreg, quiet=True, env=env) # reproject to src # switch to temp location try: grass.run_command( "v.proj", input=vreg, output=vreg, location=tgtloc, mapset=tgtmapset, quiet=True, env=src_env, ) # test if v.proj created a valid area if grass.vector_info_topo(vreg, env=src_env)["areas"] != 1: grass.fatal(_("Please check the 'extent' parameter")) except CalledModuleError: grass.fatal(_("Unable to reproject to source location")) # set region from region vector grass.run_command("g.region", raster=outfile, env=src_env) grass.run_command("g.region", vector=vreg, env=src_env) # align to first band grass.run_command("g.region", align=outfile, env=src_env) # get number of cells cells = grass.region(env=src_env)["cells"] estres = math.sqrt((n - s) * (e - w) / cells) # remove from source location for multi bands import grass.run_command("g.remove", type="vector", name=vreg, flags="f", quiet=True, env=src_env) # switch to target location grass.run_command("g.remove", type="vector", name=vreg, flags="f", quiet=True) grass.message( _("Estimated target resolution for input band <{out}>: {res}"). format(out=outfile, res=estres)) if flags["e"]: continue env = os.environ.copy() if options["extent"] == "input": env["GRASS_REGION"] = grass.region_env(n=n, s=s, e=e, w=w) res = None if tgtres == "estimated": res = estres elif tgtres == "value": res = tgtres_value grass.message( _("Using given resolution for input band <{out}>: {res}"). format(out=outfile, res=res)) # align to requested resolution env["GRASS_REGION"] = grass.region_env(res=res, flags="a", env=env) else: curr_reg = grass.region() grass.message( _("Using current region resolution for input band " "<{out}>: nsres={ns}, ewres={ew}").format( out=outfile, ns=curr_reg["nsres"], ew=curr_reg["ewres"])) # r.proj grass.message(_("Reprojecting <%s>...") % outfile) try: grass.run_command( "r.proj", location=TMPLOC, mapset="PERMANENT", input=outfile, method=method, resolution=res, memory=memory, flags=rflags, quiet=True, env=env, ) except CalledModuleError: grass.fatal(_("Unable to to reproject raster <%s>") % outfile) if grass.raster_info(outfile)["min"] is None: grass.fatal(_("The reprojected raster <%s> is empty") % outfile) if flags["e"]: return 0 if group: grass.run_command("i.group", group=output, input=",".join(outfiles)) # TODO: write metadata with r.support return 0
def main(): # check if the map is in the current mapset mapset = grass.find_file(opt['map'], element='vector')['mapset'] if not mapset or mapset != grass.gisenv()['MAPSET']: grass.fatal( _("Vector map <{}> not found in the current mapset").format( opt['map'])) # get list of existing columns try: columns = grass.vector_columns(opt['map']).keys() except CalledModuleError as e: return 1 allowed_rasters = ('N2', 'N5', 'N10', 'N20', 'N50', 'N100') # test input feature type vinfo = grass.vector_info_topo(opt['map']) if vinfo['areas'] < 1 and vinfo['points'] < 1: grass.fatal( _("No points or areas found in input vector map <{}>").format( opt['map'])) # check area size limit check_area_size = float(opt['area_size']) > 0 if check_area_size: area_col_name = 'area_{}'.format(os.getpid()) Module('v.to.db', map=opt['map'], option='area', units='kilometers', columns=area_col_name, quiet=True) areas = Module('v.db.select', flags='c', map=opt['map'], columns=area_col_name, where='{} > {}'.format(area_col_name, opt['area_size']), stdout_=grass.PIPE) large_areas = len(areas.outputs.stdout.splitlines()) if large_areas > 0: grass.warning( '{} areas larger than size limit will be skipped from computation' .format(large_areas)) # extract multi values to points for rast in opt['return_period'].split(','): # check valid rasters name = grass.find_file(rast, element='cell')['name'] if not name: grass.warning('Raster map <{}> not found. ' 'Skipped.'.format(rast)) continue if name not in allowed_rasters: grass.warning('Raster map <{}> skipped. ' 'Allowed: {}'.format(rast, allowed_rasters)) continue # perform zonal statistics grass.message('Processing <{}>...'.format(rast)) table = '{}_table'.format(name) if vinfo['areas'] > 0: Module('v.rast.stats', flags='c', map=opt['map'], raster=rast, column_prefix=name, method='average', quiet=True) # handle NULL values (areas smaller than raster resolution) null_values = Module('v.db.select', map=opt['map'], columns='cat', flags='c', where="{}_average is NULL".format(name), stdout_=grass.PIPE) cats = null_values.outputs.stdout.splitlines() if len(cats) > 0: grass.warning( _("Input vector map <{}> contains very small areas (smaller than " "raster resolution). These areas will be proceeded by querying " "single raster cell.").format(opt['map'])) Module('v.what.rast', map=opt['map'], raster=rast, type='centroid', column='{}_average'.format(name), where="{}_average is NULL".format(name), quiet=True) else: # -> points Module('v.what.rast', map=opt['map'], raster=rast, column='{}_average'.format(name), quiet=True) # add column to the attribute table if not exists rl = float(opt['rainlength']) field_name = 'H_{}T{}'.format(name, opt['rainlength']) if field_name not in columns: Module('v.db.addcolumn', map=opt['map'], columns='{} double precision'.format(field_name)) # determine coefficient for calculation a, c = coeff(rast, rl) if a is None or c is None: grass.fatal("Unable to calculate coefficients") # calculate output values, update attribute table coef = a * rl**(1 - c) expression = '{}_average * {}'.format(name, coef) Module('v.db.update', map=opt['map'], column=field_name, query_column=expression) if check_area_size: Module('v.db.update', map=opt['map'], column=field_name, value='-1', where='{} > {}'.format(area_col_name, opt['area_size'])) # remove unused column Module('v.db.dropcolumn', map=opt['map'], columns='{}_average'.format(name)) if check_area_size: # remove unused column Module('v.db.dropcolumn', map=opt['map'], columns=area_col_name) return 0
def main(): global vecttmp, tmp1, usermask, mapset input = options['input'] output = options['output'] tension = options['tension'] smooth = options['smooth'] mapset = grass.gisenv()['MAPSET'] unique = str(os.getpid()) #check if input file exists if not grass.find_file(input)['file']: grass.fatal(_("<%s> does not exist.") % input) # check if a MASK is already present: usermask = "usermask_mask." + unique if grass.find_file('MASK', mapset = mapset)['file']: grass.message(_("A user raster mask (MASK) is present. Saving it...")) grass.run_command('g.rename', quiet = True, rast = ('MASK',usermask)) #make a mask of NULL cells tmp1 = "r_fillnulls_" + unique # idea: filter all NULLS and grow that area(s) by 3 pixel, then # interpolate from these surrounding 3 pixel edge grass.message(_("Locating and isolating NULL areas...")) #creating 0/1 map: grass.mapcalc("$tmp1 = if(isnull($input),1,null())", tmp1 = tmp1, input = input) #generate a ring: # the buffer is set to three times the map resolution so you get nominally # three points around the edge. This way you interpolate into the hole with # a trained slope & curvature at the edges, otherwise you just get a flat plane. # With just a single row of cells around the hole you often get gaps # around the edges when distance > mean (.5 of the time? diagonals? worse # when ewres!=nsres). # r.buffer broken in trunk for latlon, disabled #reg = grass.region() #res = (float(reg['nsres']) + float(reg['ewres'])) * 3 / 2 #if grass.run_command('r.buffer', input = tmp1, distances = res, out = tmp1 + '.buf') != 0: # much easier way: use r.grow with radius=3.01 if grass.run_command('r.grow', input = tmp1, radius = 3.01, old = 1, new = 2, out = tmp1 + '.buf') != 0: grass.fatal(_("abandoned. Removing temporary map, restoring user mask if needed:")) grass.mapcalc("MASK=if($tmp1.buf==2,1,null())", tmp1 = tmp1) # now we only see the outlines of the NULL areas if looking at INPUT. # Use this outline (raster border) for interpolating the fill data: vecttmp = "vecttmp_fillnulls_" + unique grass.message(_("Creating interpolation points...")) if grass.run_command('r.to.vect', input = input, output = vecttmp, feature = 'point'): grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:")) # count number of points to control segmax parameter for interpolation: pointsnumber = grass.vector_info_topo(map = vecttmp)['points'] grass.message(_("Interpolating %d points") % pointsnumber) if pointsnumber < 2: grass.fatal(_("Not sufficient points to interpolate. Maybe no hole(s) to fill in the current map region?")) grass.message(_("Note: The following warnings may be ignored.")) # remove internal MASK first -- WHY???? MN 10/2005 grass.run_command('g.remove', quiet = True, rast = 'MASK') if grass.find_file(usermask, mapset = mapset)['file']: grass.message(_("Using user mask while interpolating")) maskmap = usermask else: maskmap = None segmax = 600 if pointsnumber > segmax: grass.message(_("Using segmentation for interpolation...")) segmax = None else: grass.message(_("Using no segmentation for interpolation as not needed...")) grass.run_command('v.surf.rst', input = vecttmp, elev = tmp1 + '_filled', zcol = 'value', tension = tension, smooth = smooth, maskmap = maskmap, segmax = segmax) grass.message(_("Note: Above warnings may be ignored.")) # restoring user's mask, if present: if grass.find_file(usermask, mapset = mapset)['file']: grass.message(_("Restoring user mask (MASK)...")) grass.run_command('g.rename', quiet = True, rast = (usermask, 'MASK')) # patch orig and fill map grass.message(_("Patching fill data into NULL areas...")) # we can use --o here as g.parser already checks on startup grass.run_command('r.patch', input = (input,tmp1 + '_filled'), output = output, overwrite = True) grass.message(_("Filled raster map is: %s") % output) # write cmd history: grass.raster_history(output) grass.message(_("Done."))
def main(): check_progs() inmap = options['input'] output = options['ldm'] width = options['width'] color = options['color'] graph = options['graph'] ldm_type = options['type'] mapset = grass.gisenv()['MAPSET'] global tmp, nuldev, grass_version nuldev = None grass_version = grass.version()['version'][0] if grass_version != '7': grass.fatal(_("Sorry, this script works in GRASS 7.* only")) # setup temporary files tmp = grass.tempfile() # check for LatLong location if grass.locn_is_latlong() == True: grass.fatal("Module works only in locations with cartesian coordinate system") # check if input file exists if not grass.find_file(inmap, element = 'vector')['file']: grass.fatal(_("<%s> does not exist.") % inmap) # check for lines iflines = grass.vector_info_topo(inmap)['lines'] if iflines == 0: grass.fatal(_("Map <%s> has no lines.") % inmap) # diplay options if flags['x']: env = grass.gisenv() mon = env.get('MONITOR', None) if not mon: if not graph: grass.fatal(_("Please choose \"graph\" output file with LDM graphics or not use flag \"x\"")) ####### DO IT ####### # copy input vector map and drop table grass.run_command('g.copy', vect = (inmap, 'v_ldm_vect'), quiet = True, stderr = nuldev) db = grass.vector_db('v_ldm_vect') if db != {}: grass.run_command('v.db.droptable', map_ = 'v_ldm_vect', flags = 'f', quiet = True, stderr = nuldev) # compute mean center of lines with v.mc.py module center_coords = grass.read_command('v.mc.py', input_ = inmap, type_ = 'line', quiet = True, stderr = nuldev).strip() mc_x = center_coords.split(' ')[0] mc_y = center_coords.split(' ')[1] center_coords = str(mc_x) + ',' + str(mc_y) ### inmap = 'v_ldm_vect' # count lines count = grass.vector_info_topo(inmap)['lines'] # add temp table with azimuths and lengths of lines in_cats = inmap + '_cats' grass.run_command('v.category', input_ = inmap, option = 'add', output = in_cats, quiet = True, stderr = nuldev) grass.run_command('v.db.addtable', map_ = in_cats, table = 'tmp_tab', columns = 'sum_azim double, len double', quiet = True, stderr = nuldev) grass.run_command('v.db.connect', map_ = in_cats, table = 'tmp_tab', flags = 'o', quiet = True, stderr = nuldev) grass.run_command('v.to.db', map_ = in_cats, opt = 'azimuth', columns = 'sum_azim', units = 'radians', quiet = True, stderr = nuldev) grass.run_command('v.to.db', map_ = in_cats, opt = 'length', columns = 'len', units = 'meters', quiet = True, stderr = nuldev) # find end azimuth p = grass.pipe_command('v.db.select', map_ = in_cats, columns = 'sum_azim', flags = 'c', quiet = True, stderr = nuldev) c = p.communicate()[0].strip().split('\n') sin = [] cos = [] for i in c: s1 = math.sin(float(i)) c1 = math.cos(float(i)) sin.append(s1) cos.append(c1) ca_sin = sum(map(float,sin)) ca_cos = sum(map(float,cos)) atan = math.atan2(ca_sin,ca_cos) end_azim = math.degrees(atan) # find compass angle if end_azim < 0: a2 = -(end_azim) if end_azim > 0: a2 = end_azim if (ca_sin > 0) and (ca_cos > 0): comp_angle = a2 if (ca_sin > 0) and (ca_cos < 0): comp_angle = a2 if (ca_sin < 0) and (ca_cos > 0): comp_angle = 360 - a2 if (ca_sin < 0) and (ca_cos < 0): comp_angle = 360 - a2 # find LDM if end_azim < 0: a2 = -(end_azim) if end_azim > 0: a2 = end_azim if (ca_sin > 0) and (ca_cos > 0): ldm = 90 - a2 if (ca_sin > 0) and (ca_cos < 0): ldm = 450 - a2 if (ca_sin < 0) and (ca_cos > 0): ldm = 90 + a2 if (ca_sin < 0) and (ca_cos < 0): ldm = 90 + a2 # find circular variance sin_pow = math.pow(ca_sin,2) cos_pow = math.pow(ca_cos,2) circ_var = 1-(math.sqrt(sin_pow+cos_pow))/count # find start/end points of "mean" line end_azim_dms = decimal2dms(end_azim) # if end_azim < 0: # end_azim_dms = '-' + (str(end_azim_dms)) start_azim = 180 - end_azim start_azim_dms = decimal2dms(start_azim) p = grass.pipe_command('v.db.select', map_ = in_cats, columns = 'len', flags = 'c', quiet = True, stderr = nuldev) c = p.communicate()[0].strip().split('\n') mean_length = sum(map(float,c))/len(c) half_length = float(mean_length)/2 tmp1 = tmp + '.inf' inf1 = file(tmp1, 'w') print >> inf1, 'N ' + str(end_azim_dms) + ' E ' + str(half_length) inf1.close() end_coords = grass.read_command('m.cogo', input_ = tmp1, output = '-', coord = center_coords, quiet = True).strip() tmp2 = tmp + '.inf2' inf2 = file(tmp2, 'w') print >> inf2, 'N ' + str(start_azim_dms) + ' W ' + str(half_length) inf2.close() start_coords = grass.read_command('m.cogo', input_ = tmp2, output = '-', coord = center_coords, quiet = True).strip() # make "arrowhead" symbol if flags['x'] or graph: tmp3 = tmp + '.arrowhead_1' outf3 = file(tmp3, 'w') if ldm_type == 'direct': t1 = """VERSION 1.0 BOX -0.5 -0.5 0.5 0.5 POLYGON RING FCOLOR NONE LINE 0 0 0.3 -1 END END POLYGON RING FCOLOR NONE LINE 0 0 -0.3 -1 END END END """ outf3.write(t1) outf3.close() gisdbase = grass.gisenv()['GISDBASE'] location = grass.gisenv()['LOCATION_NAME'] mapset = grass.gisenv()['MAPSET'] symbols_dir = os.path.join(gisdbase, location, mapset, 'symbol', 'arrows') symbol = os.path.join(symbols_dir, 'arrowhead_1') if not os.path.exists(symbols_dir): try: os.makedirs(symbols_dir) except OSError: pass if not os.path.isfile(symbol): shutil.copyfile(tmp3, symbol) # write LDM graph file and optionally display line of LDM with an arrow tmp4 = tmp + '.ldm' outf4 = file(tmp4, 'w') arrow_size = int(width) * 1.4 arrow_azim = 360 - float(end_azim) if ldm_type == 'direct': t2 = string.Template(""" move $start_coords width $width color $color draw $end_coords rotation $arrow_azim width $width symbol $symbol_s $arrow_size $end_coords $color """) s2 = t2.substitute(start_coords = start_coords, width = width, color = color, end_coords = end_coords, arrow_azim = arrow_azim, symbol_s = "arrows/arrowhead_1", arrow_size = arrow_size) else: t2 = string.Template(""" move $start_coords width $width color $color draw $end_coords """) s2 = t2.substitute(start_coords = start_coords, width = width, color = color, end_coords = end_coords) outf4.write(s2) outf4.close() if graph: shutil.copy(tmp4, graph) # save LDM line to vector if option "output" set if output: tmp5 = tmp + '.line' outf5 = file(tmp5, 'w') print >> outf5, str(start_coords) print >> outf5, str(end_coords) outf5.close() grass.run_command('v.in.lines', input_ = tmp5, output = output, separator = " ", overwrite = True, quiet = True) out_cats = output + '_cats' grass.run_command('v.category', input_ = output, option = 'add', output = out_cats, quiet = True, stderr = nuldev) grass.run_command('g.rename', vect = (out_cats,output), overwrite = True, quiet = True, stderr = nuldev) if circ_var: col = 'comp_angle double,dir_mean double,cir_var double,ave_x double,ave_y double,ave_len double' else: col = 'comp_angle double,dir_mean double,ave_x double,ave_y double,ave_len double' grass.run_command('v.db.addtable', map_ = output, columns = col, quiet = True, stderr = nuldev) tmp6 = tmp + '.sql' outf6 = file(tmp6, 'w') t3 = string.Template(""" UPDATE $output SET comp_angle = $comp_angle; UPDATE $output SET dir_mean = $ldm; UPDATE $output SET ave_x = $mc_x; UPDATE $output SET ave_y = $mc_y; UPDATE $output SET ave_len = $mean_length; """) s3 = t3.substitute(output = output, comp_angle = ("%0.3f" % comp_angle), ldm = ("%0.3f" % ldm), mc_x = ("%0.3f" % float(mc_x)), mc_y = ("%0.3f" % float(mc_y)), mean_length = ("%0.3f" % mean_length)) outf6.write(s3) if circ_var: print >> outf6, "UPDATE %s SET cir_var = %0.3f;" % (output, circ_var) outf6.close() grass.run_command('db.execute', input_ = tmp6, quiet = True, stderr = nuldev) # print LDM parameters to stdout (with <-g> flag in shell style): print_out = ['Compass Angle', 'Directional Mean', 'Average Center', 'Average Length'] if circ_var: print_out.append('Circular Variance') print_shell = ['compass_angle', 'directional_mean', 'average_center', 'average_length', 'circular_variance'] if circ_var: print_shell.append('circular_variance') print_vars = ["%0.3f" % comp_angle, "%0.3f" % ldm, "%0.3f" % float(mc_x) + ',' + "%0.3f" % float(mc_y), "%0.3f" % mean_length] if circ_var: print_vars.append("%0.3f" % circ_var) if flags['g']: for i,j in zip(print_shell, print_vars): print "%s=%s" % (i, j) else: for i,j in zip(print_out, print_vars): print "%s: %s" % (i, j) # diplay LDM graphics if flags['x']: if mon: if graph: grass.run_command('d.graph', input_ = graph, flags = 'm', quiet = True, stderr = nuldev) else: grass.run_command('d.graph', input_ = tmp4, flags = 'm', quiet = True, stderr = nuldev) elif graph: grass.message(_("\n Use this command in wxGUI \"Command console\" or with <d.mon> or with \"command layer\" to display LDM graphics: \n d.graph -m input=%s \n\n" ) % graph)
def main(): raster = options["raster"] maskcats = options["maskcats"] vector = options["vector"] layer = options["layer"] cats = options["cats"] where = options["where"] remove = flags["r"] invert = flags["i"] if not remove and not raster and not vector: grass.fatal( _("Either parameter <raster> or parameter <vector> is required")) mapset = grass.gisenv()["MAPSET"] exists = bool( grass.find_file("MASK", element="cell", mapset=mapset)["file"]) if remove: # -> remove if exists: if sys.platform == "win32": grass.run_command("g.remove", flags="if", quiet=True, type="raster", name="MASK") else: grass.run_command("g.remove", flags="f", quiet=True, type="raster", name="MASK") grass.message(_("Raster MASK removed")) else: grass.fatal(_("No existing MASK to remove")) else: # -> create if exists: if not grass.overwrite(): grass.fatal( _("MASK already found in current mapset. Delete first or overwrite." )) else: grass.warning(_("MASK already exists and will be overwritten")) grass.run_command("g.remove", flags="f", quiet=True, type="raster", name="MASK") if raster: # check if input raster exists if not grass.find_file(raster)["file"]: grass.fatal(_("Raster map <%s> not found") % raster) if maskcats != "*" and not remove: if grass.raster_info(raster)["datatype"] != "CELL": grass.fatal( _("The raster map <%s> must be integer (CELL type) " " in order to use the 'maskcats' parameter") % raster) p = grass.feed_command("r.reclass", input=raster, output="MASK", overwrite=True, rules="-") res = "%s = 1" % maskcats p.stdin.write(encode(res)) p.stdin.close() p.wait() elif vector: vector_name = grass.find_file(vector, "vector")["fullname"] if not vector_name: grass.fatal(_("Vector map <%s> not found") % vector) # parser bug? if len(cats) == 0: cats = None if len(where) == 0: where = None if grass.vector_info_topo(vector_name)["areas"] < 1: grass.warning( _("No area found in vector map <%s>. " "Creating a convex hull for MASK.") % vector_name) global tmp_hull tmp_hull = "tmp_hull_%d" % os.getpid() to_rast_input = tmp_hull # force 'flat' convex hull for 3D vector maps try: grass.run_command( "v.hull", flags="f", quiet=True, input=vector_name, output=tmp_hull, layer=layer, cats=cats, where=where, ) except CalledModuleError: grass.fatal( _("Unable to create a convex hull for vector map <%s>") % vector_name) else: to_rast_input = vector_name env = os.environ.copy() if grass.verbosity() > 1: env["GRASS_VERBOSE"] = "1" grass.run_command( "v.to.rast", input=to_rast_input, layer=layer, output="MASK", use="val", val="1", type="area", cats=cats, where=where, env=env, ) if invert: global tmp tmp = "r_mask_%d" % os.getpid() grass.run_command("g.rename", raster=("MASK", tmp), quiet=True) grass.message(_("Creating inverted raster MASK...")) grass.mapcalc("MASK = if(isnull($tmp), 1, null())", tmp=tmp) grass.verbose(_("Inverted raster MASK created")) else: grass.verbose(_("Raster MASK created")) grass.message( _("All subsequent raster operations will be limited to " "the MASK area. Removing or renaming raster map named " "'MASK' will restore raster operations to normal."))
def main(): global tmp, tmp_proj, tmp_gpx, tmp_extr, tmp_vogb format = options['format'] input = options['input'] layer = options['layer'] output = options['output'] type = options['type'] where = options['where'] wpt = flags['w'] rte = flags['r'] trk = flags['t'] nflags = len(filter(None, [wpt, rte, trk])) if nflags > 1: grass.fatal(_("One feature at a time please.")) if nflags < 1: grass.fatal(_("No features requested for export.")) # set some reasonable defaults if not type: if wpt: type = 'point' else: type = 'line' #### check for gpsbabel ### FIXME: may need --help or similar? if not grass.find_program("gpsbabel"): grass.fatal(_("The gpsbabel program was not found, please install it first.\n") + "http://gpsbabel.sourceforge.net") #### check for cs2cs if not grass.find_program("cs2cs"): grass.fatal(_("The cs2cs program was not found, please install it first.\n") + "http://proj.osgeo.org") # check if we will overwrite data if os.path.exists(output) and not grass.overwrite(): grass.fatal(_("Output file already exists.")) #### set temporary files tmp = grass.tempfile() # SQL extract if needed if where: grass.verbose("Extracting data ...") tmp_extr = "tmp_vogb_extr_%d" % os.getpid() ret = grass.run_command('v.extract', input = "$GIS_OPT_INPUT", output = tmp_extr, type = type, layer = layer, where = where, quiet = True) if ret != 0: grass.fatal(_("Error executing SQL query")) kv = grass.vector_info_topo(tmp_extr) if kv['primitives'] == 0: grass.fatal(_("SQL query returned an empty map (no %s features?)") % type) inmap = tmp_extr else: # g.copy "$GIS_OPT_INPUT,tmp_vogb_extr_$$" # to get a copy of DB into local mapset # INMAP="tmp_vogb_extr_$$" inmap = input #### set up projection info # TODO: check if we are already in ll/WGS84. If so skip m.proj step. # TODO: multi layer will probably fail badly due to sed 's/^ 1 /' # output as old GRASS 4 vector ascii and fight with dig_ascii/? # Change to s/^ \([0-9] .*\) /# \1/' ??? mmph. # reproject to lat/lon WGS84 grass.verbose("Reprojecting data ...") re1 = re.compile(r'^\([PLBCFKA]\)') re2 = re.compile(r'^ 1 ') re3 = re.compile(r'\t\([-\.0-9]*\) .*') re4 = re.compile(r'^\([-\.0-9]\)') re5 = re.compile(r'^#') tmp_proj = tmp + ".proj" tf = open(tmp_proj, 'w') p1 = grass.pipe_command('v.out.ascii', input = inmap, format = 'standard') p2 = grass.feed_command('m.proj', input = '-', flags = 'od', quiet = True, stdout = tf) tf.close() lineno = 0 for line in p1.stdout: lineno += 1 if lineno < 11: continue line = re1.sub(r'#\1', line) line = re2.sub(r'# 1 ', line) p2.stdin.write(line) p2.stdin.close() p1.wait() p2.wait() if p1.returncode != 0 or p2.returncode != 0: grass.fatal(_("Error reprojecting data")) tmp_vogb = "tmp_vogb_epsg4326_%d" % os.getpid() p3 = grass.feed_command('v.in.ascii', out = tmp_vogb, format = 'standard', flags = 'n', quiet = True) tf = open(tmp_proj, 'r') for line in tf: line = re3.sub(r' \1', line) line = re4.sub(r' \1', line) line = re5.sub('', line) p3.stdin.write(line) p3.stdin.close() tf.close() p3.wait() if p3.returncode != 0: grass.fatal(_("Error reprojecting data")) # don't v.db.connect directly as source table will be removed with # temporary map in that case. So we make a temp copy of it to work with. kv = vector_db(inmap) if layer in kv: db_params = kv[layer] db_table = db_params['table'] db_key = db_params['key'] db_database = db_params['database'] db_driver = db_params['driver'] ret = grass.run_command('db.copy', from_driver = db_driver, from_database = db_database, from_table = db_table, to_table = tmp_vogb) if ret != 0: grass.fatal(_("Error copying temporary DB")) ret = grass.run_command('v.db.connect', map = tmp_vogb, table = tmp_vogb, quiet = True) if ret != 0: grass.fatal(_("Error reconnecting temporary DB")) # export as GPX using v.out.ogr if trk: linetype = "FORCE_GPX_TRACK=YES" elif rte: linetype = "FORCE_GPX_TRACK=YES" else: linetype = None # BUG: cat is being reported as evelation and attribute output is skipped. # (v.out.ogr DB reading or ->OGR GPX driver bug<- # resolved: see new Create opts at http://www.gdal.org/ogr/drv_gpx.html) # v.out.ogr -> shapefile -> GPX works, but we try to avoid that as it's # lossy. Also that would allow ogr2ogr -a_srs $IN_PROJ -t_srs EPSG:4326 # so skip m.proj pains.. if that is done ogr2ogr -s_srs MUST HAVE +wktext # with PROJ.4 terms or else the +nadgrids will be ignored! best to feed # it IN_PROJ="`g.proj -jf` +wktext" in that case. grass.verbose("Exporting data ...") tmp_gpx = tmp + ".gpx" ret = grass.run_command('v.out.ogr', input = tmp_vogb, dsn = tmp_gpx, type = type, format = 'GPX', lco = linetype, dsco = "GPX_USE_EXTENSIONS=YES", quiet = True) if ret != 0: grass.fatal(_("Error exporting data")) if format == 'gpx': # short circuit, we have what we came for. grass.try_remove(output) os.rename(tmp_gpx, output) grass.verbose("Fast exit.") sys.exit() # run gpsbabel if wpt: gtype = '-w' elif trk: gtype = '-t' elif rte: gtype = '-r' else: gtype = '' grass.verbose("Running GPSBabel ...") ret = grass.call(['gpsbabel', gtype, '-i', 'gpx', '-f', tmp + '.gpx', '-o', format, '-F', output]) if ret != 0: grass.fatal(_("Error running GPSBabel")) grass.verbose("Done.")
def main(): input = options['input'] output = options['output'] column = options['column'] ftype = options['type'] xtiles = int(options['x']) ytiles = int(options['y']) rtvflags = "" for key in 'sbtvz': if flags[key]: rtvflags += key # check options if xtiles <= 0: grass.fatal(_("Number of tiles in x direction must be > 0")) if ytiles < 0: grass.fatal(_("Number of tiles in y direction must be > 0")) if grass.find_file(name=input)['name'] == '': grass.fatal(_("Input raster %s not found") % input) grass.use_temp_region() curr = grass.region() width = int(curr['cols'] / xtiles) if width <= 1: grass.fatal( "The requested number of tiles in x direction is too large") height = int(curr['rows'] / ytiles) if height <= 1: grass.fatal( "The requested number of tiles in y direction is too large") do_clip = False overlap = 0 if flags['s'] and ftype == 'area': do_clip = True overlap = 2 ewres = curr['ewres'] nsres = curr['nsres'] xoverlap = overlap * ewres yoverlap = overlap * nsres xoverlap2 = (overlap / 2) * ewres yoverlap2 = (overlap / 2) * nsres e = curr['e'] w = curr['w'] + xoverlap if w >= e: grass.fatal(_("Overlap is too large")) n = curr['n'] - yoverlap s = curr['s'] if s >= n: grass.fatal(_("Overlap is too large")) datatype = grass.raster_info(input)['datatype'] vtiles = None # north to south for ytile in range(ytiles): n = curr['n'] - ytile * height * nsres s = n - height * nsres - yoverlap if ytile == ytiles - 1: s = curr['s'] # west to east for xtile in range(xtiles): w = curr['w'] + xtile * width * ewres e = w + width * ewres + xoverlap if xtile == xtiles - 1: e = curr['e'] grass.run_command('g.region', n=n, s=s, e=e, w=w, nsres=nsres, ewres=ewres) if do_clip: tilename = output + '_stile_' + str(ytile) + str(xtile) else: tilename = output + '_tile_' + str(ytile) + str(xtile) outname = output + '_tile_' + str(ytile) + str(xtile) grass.run_command('r.to.vect', input=input, output=tilename, type=ftype, column=column, flags=rtvflags) if do_clip: n2 = curr['n'] - ytile * height * nsres - yoverlap2 s2 = n2 - height * nsres if ytile == 0: n2 = curr['n'] s2 = n2 - height * nsres - yoverlap2 if ytile == ytiles - 1: s2 = curr['s'] w2 = curr['w'] + xtile * width * ewres + xoverlap2 e2 = w2 + width * ewres if xtile == 0: w2 = curr['w'] e2 = w2 + width * ewres + xoverlap2 if xtile == xtiles - 1: e2 = curr['e'] tilename = output + '_stile_' + str(ytile) + str(xtile) if grass.vector_info_topo(tilename)['areas'] > 0: grass.run_command('g.region', n=n2, s=s2, e=e2, w=w2, nsres=nsres, ewres=ewres) extname = 'extent_tile_' + str(ytile) + str(xtile) grass.run_command('v.in.region', output=extname, flags='d') outname = output + '_tile_' + str(ytile) + str(xtile) grass.run_command('v.overlay', ainput=tilename, binput=extname, output=outname, operator='and', olayer='0,1,0') grass.run_command('g.remove', flags='f', type='vector', name=extname, quiet=True) if vtiles is None: vtiles = outname else: vtiles = vtiles + ',' + outname grass.run_command('g.remove', flags='f', type='vector', name=tilename, quiet=True) else: # write cmd history: grass.vector_history(outname) if vtiles is None: vtiles = outname else: vtiles = vtiles + ',' + outname if flags['p']: grass.run_command('v.patch', input=vtiles, output=output, flags='e') grass.run_command('g.remove', flags='f', type='vector', name=vtiles, quiet=True) if grass.vector_info_topo(output)['boundaries'] > 0: outpatch = output + '_patch' grass.run_command('g.rename', vector=(output, outpatch)) grass.run_command('v.clean', input=outpatch, output=output, tool='break', flags='c') grass.run_command('g.remove', flags='f', type='vector', name=outpatch) grass.message(_("%s complete") % 'r.to.vect.tiled') return 0
def main(): input_map = opt['input'] clip_map = opt['clip'] output_map = opt['output'] flag_dissolve = flg['d'] flag_region = flg['r'] # ======================================== # # ========== INPUT MAP TOPOLOGY ========== # # ======================================== # vinfo = grass.vector_info_topo(input_map) # ==== only points ==== # if (vinfo['points'] > 0 and vinfo['lines'] == 0 and vinfo['areas'] == 0): # ==================================== # # ========== CLIP BY REGION ========== # # ==================================== # if (flag_region): clip_by_region(input_map, output_map, clip_select) # ================================== # # ========== DEFAULT CLIP ========== # # ================================== # else: section_message("Clipping.") # perform clipping clip_select(input_map, clip_map, output_map) # ==== lines, areas, lines + areas ==== # # ==== points + areas, points + lines, points + areas + lines ==== # else: if (vinfo['points'] > 0): grass.warning("Input map contains multiple geometry, " "only lines and areas will be clipped.") # ==================================== # # ========== CLIP BY REGION ========== # # ==================================== # if (flag_region): clip_by_region(input_map, output_map, clip_overlay) # ===================================================== # # ========== CLIP WITHOUT DISSOLVED CLIP MAP ========== # # ===================================================== # elif (flag_dissolve): section_message("Clipping without dissolved clip map.") clip_overlay(input_map, clip_map, output_map) # ========================================================== # # ========== DEFAULT CLIP WITH DISSOLVED CLIP MAP ========== # # ========================================================== # else: section_message("Default clipping with dissolved clip map.") # setup temporary map temp_clip_map = '%s_%s' % ("temp", str(os.getpid())) TMP.append(temp_clip_map) # dissolve clip_map grass.run_command('v.dissolve', input=clip_map, output=temp_clip_map) # perform clipping clip_overlay(input_map, temp_clip_map, output_map) # ======================================== # # ========== OUTPUT MAP TOPOLOGY========== # # ======================================== # vinfo = grass.vector_info_topo(output_map) if vinfo['primitives'] == 0: grass.warning("Output map is empty.") return 0
def main(): # check if the map is in the current mapset mapset = grass.find_file(opt["map"], element="vector")["mapset"] if not mapset or mapset != grass.gisenv()["MAPSET"]: grass.fatal( _("Vector map <{}> not found in the current mapset").format( opt["map"])) # get list of existing columns try: columns = grass.vector_columns(opt["map"]).keys() except CalledModuleError as e: return 1 allowed_rasters = ("N2", "N5", "N10", "N20", "N50", "N100") # test input feature type vinfo = grass.vector_info_topo(opt["map"]) if vinfo["areas"] < 1 and vinfo["points"] < 1: grass.fatal( _("No points or areas found in input vector map <{}>").format( opt["map"])) # check area size limit check_area_size = float(opt["area_size"]) > 0 if check_area_size: area_col_name = "area_{}".format(os.getpid()) Module( "v.to.db", map=opt["map"], option="area", units="kilometers", columns=area_col_name, quiet=True, ) areas = Module( "v.db.select", flags="c", map=opt["map"], columns=area_col_name, where="{} > {}".format(area_col_name, opt["area_size"]), stdout_=grass.PIPE, ) large_areas = len(areas.outputs.stdout.splitlines()) if large_areas > 0: grass.warning( "{} areas larger than size limit will be skipped from computation" .format(large_areas)) # extract multi values to points for rast in opt["return_period"].split(","): # check valid rasters name = grass.find_file(rast, element="cell")["name"] if not name: grass.warning("Raster map <{}> not found. " "Skipped.".format(rast)) continue if name not in allowed_rasters: grass.warning("Raster map <{}> skipped. " "Allowed: {}".format(rast, allowed_rasters)) continue # perform zonal statistics grass.message("Processing <{}>...".format(rast)) table = "{}_table".format(name) if vinfo["areas"] > 0: Module( "v.rast.stats", flags="c", map=opt["map"], raster=rast, column_prefix=name, method="average", quiet=True, ) # handle NULL values (areas smaller than raster resolution) null_values = Module( "v.db.select", map=opt["map"], columns="cat", flags="c", where="{}_average is NULL".format(name), stdout_=grass.PIPE, ) cats = null_values.outputs.stdout.splitlines() if len(cats) > 0: grass.warning( _("Input vector map <{}> contains very small areas (smaller than " "raster resolution). These areas will be proceeded by querying " "single raster cell.").format(opt["map"])) Module( "v.what.rast", map=opt["map"], raster=rast, type="centroid", column="{}_average".format(name), where="{}_average is NULL".format(name), quiet=True, ) else: # -> points Module( "v.what.rast", map=opt["map"], raster=rast, column="{}_average".format(name), quiet=True, ) # add column to the attribute table if not exists rl = float(opt["rainlength"]) field_name = "H_{}T{}".format(name, opt["rainlength"]) if field_name not in columns: Module( "v.db.addcolumn", map=opt["map"], columns="{} double precision".format(field_name), ) # determine coefficient for calculation a, c = coeff(rast, rl) if a is None or c is None: grass.fatal("Unable to calculate coefficients") # calculate output values, update attribute table coef = a * rl**(1 - c) expression = "{}_average * {}".format(name, coef) Module("v.db.update", map=opt["map"], column=field_name, query_column=expression) if check_area_size: Module( "v.db.update", map=opt["map"], column=field_name, value="-1", where="{} > {}".format(area_col_name, opt["area_size"]), ) # remove unused column Module("v.db.dropcolumn", map=opt["map"], columns="{}_average".format(name)) if check_area_size: # remove unused column Module("v.db.dropcolumn", map=opt["map"], columns=area_col_name) return 0
def main(): raster = options['raster'] maskcats = options['maskcats'] vector = options['vector'] layer = options['layer'] cats = options['cats'] where = options['where'] remove = flags['r'] invert = flags['i'] if not remove and not raster and not vector: grass.fatal(_("Either parameter <raster> ot parameter <vector> is required")) mapset = grass.gisenv()['MAPSET'] exists = bool(grass.find_file('MASK', element='cell', mapset=mapset)['file']) if remove: # -> remove if exists: if sys.platform == 'win32': grass.run_command('g.remove', flags='if', quiet=True, type='raster', name='MASK') else: grass.run_command('g.remove', flags='f', quiet=True, type='raster', name='MASK') grass.message(_("Raster MASK removed")) else: grass.fatal(_("No existing MASK to remove")) else: # -> create if exists: if not grass.overwrite(): grass.fatal(_("MASK already found in current mapset. Delete first or overwrite.")) else: grass.warning(_("MASK already exists and will be overwritten")) grass.run_command('g.remove', flags='f', quiet=True, type='raster', name='MASK') if raster: # check if input raster exists if not grass.find_file(raster)['file']: grass.fatal(_("Raster map <%s> not found") % raster) if maskcats != '*' and not remove: if grass.raster_info(raster)['datatype'] != "CELL": grass.fatal(_("The raster map <%s> must be integer (CELL type) " " in order to use the 'maskcats' parameter") % raster) p = grass.feed_command( 'r.reclass', input=raster, output='MASK', overwrite=True, rules='-') p.stdin.write("%s = 1" % maskcats) p.stdin.close() p.wait() elif vector: vector_name = grass.find_file(vector, 'vector')['fullname'] if not vector_name: grass.fatal(_("Vector map <%s> not found") % vector) # parser bug? if len(cats) == 0: cats = None if len(where) == 0: where = None if grass.vector_info_topo(vector_name)['areas'] < 1: grass.warning(_("No area found in vector map <%s>. " "Creating a convex hull for MASK.") % vector_name) global tmp_hull tmp_hull = "tmp_hull_%d" % os.getpid() to_rast_input = tmp_hull # force 'flat' convex hull for 3D vector maps try: grass.run_command('v.hull', flags='f', quiet=True, input=vector_name, output=tmp_hull, layer=layer, cats=cats, where=where) except CalledModuleError: grass.fatal( _("Unable to create a convex hull for vector map <%s>") % vector_name) else: to_rast_input = vector_name env = os.environ.copy() if grass.verbosity() > 1: env['GRASS_VERBOSE'] = '1' grass.run_command('v.to.rast', input=to_rast_input, layer=layer, output='MASK', use='val', val='1', type='area', cats=cats, where=where, env=env) if invert: global tmp tmp = "r_mask_%d" % os.getpid() grass.run_command('g.rename', raster=('MASK', tmp), quiet=True) grass.message(_("Creating inverted raster MASK...")) grass.mapcalc("MASK = if(isnull($tmp), 1, null())", tmp=tmp) grass.verbose(_("Inverted raster MASK created")) else: grass.verbose(_("Raster MASK created")) grass.message(_("All subsequent raster operations will be limited to " "the MASK area. Removing or renaming raster map named " "'MASK' will restore raster operations to normal."))
def main(): input = options["input"] output = options["output"] column = options["column"] ftype = options["type"] xtiles = int(options["x"]) ytiles = int(options["y"]) rtvflags = "" for key in "sbtvz": if flags[key]: rtvflags += key # check options if xtiles <= 0: grass.fatal(_("Number of tiles in x direction must be > 0")) if ytiles < 0: grass.fatal(_("Number of tiles in y direction must be > 0")) if grass.find_file(name=input)["name"] == "": grass.fatal(_("Input raster %s not found") % input) grass.use_temp_region() curr = grass.region() width = int(curr["cols"] / xtiles) if width <= 1: grass.fatal("The requested number of tiles in x direction is too large") height = int(curr["rows"] / ytiles) if height <= 1: grass.fatal("The requested number of tiles in y direction is too large") do_clip = False overlap = 0 if flags["s"] and ftype == "area": do_clip = True overlap = 2 ewres = curr["ewres"] nsres = curr["nsres"] xoverlap = overlap * ewres yoverlap = overlap * nsres xoverlap2 = (overlap / 2) * ewres yoverlap2 = (overlap / 2) * nsres e = curr["e"] w = curr["w"] + xoverlap if w >= e: grass.fatal(_("Overlap is too large")) n = curr["n"] - yoverlap s = curr["s"] if s >= n: grass.fatal(_("Overlap is too large")) datatype = grass.raster_info(input)["datatype"] vtiles = None # north to south for ytile in range(ytiles): n = curr["n"] - ytile * height * nsres s = n - height * nsres - yoverlap if ytile == ytiles - 1: s = curr["s"] # west to east for xtile in range(xtiles): w = curr["w"] + xtile * width * ewres e = w + width * ewres + xoverlap if xtile == xtiles - 1: e = curr["e"] grass.run_command("g.region", n=n, s=s, e=e, w=w, nsres=nsres, ewres=ewres) if do_clip: tilename = output + "_stile_" + str(ytile) + str(xtile) else: tilename = output + "_tile_" + str(ytile) + str(xtile) outname = output + "_tile_" + str(ytile) + str(xtile) grass.run_command( "r.to.vect", input=input, output=tilename, type=ftype, column=column, flags=rtvflags, ) if do_clip: n2 = curr["n"] - ytile * height * nsres - yoverlap2 s2 = n2 - height * nsres if ytile == 0: n2 = curr["n"] s2 = n2 - height * nsres - yoverlap2 if ytile == ytiles - 1: s2 = curr["s"] w2 = curr["w"] + xtile * width * ewres + xoverlap2 e2 = w2 + width * ewres if xtile == 0: w2 = curr["w"] e2 = w2 + width * ewres + xoverlap2 if xtile == xtiles - 1: e2 = curr["e"] tilename = output + "_stile_" + str(ytile) + str(xtile) if grass.vector_info_topo(tilename)["areas"] > 0: grass.run_command( "g.region", n=n2, s=s2, e=e2, w=w2, nsres=nsres, ewres=ewres ) extname = "extent_tile_" + str(ytile) + str(xtile) grass.run_command("v.in.region", output=extname, flags="d") outname = output + "_tile_" + str(ytile) + str(xtile) grass.run_command( "v.overlay", ainput=tilename, binput=extname, output=outname, operator="and", olayer="0,1,0", ) grass.run_command( "g.remove", flags="f", type="vector", name=extname, quiet=True ) if vtiles is None: vtiles = outname else: vtiles = vtiles + "," + outname grass.run_command( "g.remove", flags="f", type="vector", name=tilename, quiet=True ) else: # write cmd history: grass.vector_history(outname) if vtiles is None: vtiles = outname else: vtiles = vtiles + "," + outname if flags["p"]: grass.run_command("v.patch", input=vtiles, output=output, flags="e") grass.run_command("g.remove", flags="f", type="vector", name=vtiles, quiet=True) if grass.vector_info_topo(output)["boundaries"] > 0: outpatch = output + "_patch" grass.run_command("g.rename", vector=(output, outpatch)) grass.run_command( "v.clean", input=outpatch, output=output, tool="break", flags="c" ) grass.run_command("g.remove", flags="f", type="vector", name=outpatch) grass.message(_("%s complete") % "r.to.vect.tiled") return 0
def main(): global tmp, sqltmp, tmpname, nuldev, vector, rastertmp rastertmp = False # setup temporary files tmp = grass.tempfile() sqltmp = tmp + ".sql" # we need a random name tmpname = grass.basename(tmp) nuldev = open(os.devnull, 'w') rasters = options['raster'].split(',') colprefixes = options['column_prefix'].split(',') vector = options['map'] layer = options['layer'] percentile = options['percentile'] basecols = options['method'].split(',') ### setup enviro vars ### env = grass.gisenv() mapset = env['MAPSET'] vs = vector.split('@') if len(vs) > 1: vect_mapset = vs[1] else: vect_mapset = mapset # does map exist in CURRENT mapset? if vect_mapset != mapset or not grass.find_file(vector, 'vector', mapset)['file']: grass.fatal(_("Vector map <%s> not found in current mapset") % vector) # check if DBF driver used, in this case cut to 10 chars col names: try: fi = grass.vector_db(map=vector)[int(layer)] except KeyError: grass.fatal( _('There is no table connected to this map. Run v.db.connect or v.db.addtable first.' )) # we need this for non-DBF driver: dbfdriver = fi['driver'] == 'dbf' # colprefix for every raster map? if len(colprefixes) != len(rasters): grass.fatal( _("Number of raster maps ({0}) different from \ number of column prefixes ({1})".format( len(rasters), len(colprefixes)))) vector = vs[0] rastertmp = "%s_%s" % (vector, tmpname) for raster in rasters: # check the input raster map if not grass.find_file(raster, 'cell')['file']: grass.fatal(_("Raster map <%s> not found") % raster) # save current settings: grass.use_temp_region() # Temporarily aligning region resolution to $RASTER resolution # keep boundary settings grass.run_command('g.region', align=rasters[0]) # prepare base raster for zonal statistics try: nlines = grass.vector_info_topo(vector)['lines'] # Create densified lines rather than thin lines if flags['d'] and nlines > 0: grass.run_command('v.to.rast', input=vector, layer=layer, output=rastertmp, use='cat', flags='d', quiet=True) else: grass.run_command('v.to.rast', input=vector, layer=layer, output=rastertmp, use='cat', quiet=True) except CalledModuleError: grass.fatal(_("An error occurred while converting vector to raster")) # dump cats to file to avoid "too many argument" problem: p = grass.pipe_command('r.category', map=rastertmp, sep=';', quiet=True) cats = [] for line in p.stdout: line = decode(line) cats.append(line.rstrip('\r\n').split(';')[0]) p.wait() number = len(cats) if number < 1: grass.fatal(_("No categories found in raster map")) # Check if all categories got converted # Report categories from vector map vect_cats = grass.read_command('v.category', input=vector, option='report', flags='g').rstrip('\n').split('\n') # get number of all categories in selected layer for vcl in vect_cats: if vcl.split(' ')[0] == layer and vcl.split(' ')[1] == 'all': vect_cats_n = int(vcl.split(' ')[2]) if vect_cats_n != number: grass.warning( _("Not all vector categories converted to raster. \ Converted {0} of {1}.".format(number, vect_cats_n))) # check if DBF driver used, in this case cut to 10 chars col names: try: fi = grass.vector_db(map=vector)[int(layer)] except KeyError: grass.fatal( _('There is no table connected to this map. Run v.db.connect or v.db.addtable first.' )) # we need this for non-DBF driver: dbfdriver = fi['driver'] == 'dbf' # Find out which table is linked to the vector map on the given layer if not fi['table']: grass.fatal( _('There is no table connected to this map. Run v.db.connect or v.db.addtable first.' )) # replaced by user choiche #basecols = ['n', 'min', 'max', 'range', 'mean', 'stddev', 'variance', 'cf_var', 'sum'] for i in xrange(len(rasters)): raster = rasters[i] colprefix = colprefixes[i] # we need at least three chars to distinguish [mea]n from [med]ian # so colprefix can't be longer than 6 chars with DBF driver if dbfdriver: colprefix = colprefix[:6] variables_dbf = {} # by default perccol variable is used only for "variables" variable perccol = "percentile" perc = None for b in basecols: if b.startswith('p'): perc = b if perc: # namespace is limited in DBF but the % value is important if dbfdriver: perccol = "per" + percentile else: perccol = "percentile_" + percentile percindex = basecols.index(perc) basecols[percindex] = perccol # dictionary with name of methods and position in "r.univar -gt" output variables = { 'number': 2, 'null_cells': 2, 'minimum': 4, 'maximum': 5, 'range': 6, 'average': 7, 'stddev': 9, 'variance': 10, 'coeff_var': 11, 'sum': 12, 'first_quartile': 14, 'median': 15, 'third_quartile': 16, perccol: 17 } # this list is used to set the 'e' flag for r.univar extracols = ['first_quartile', 'median', 'third_quartile', perccol] addcols = [] colnames = [] extstat = "" for i in basecols: # this check the complete name of out input that should be truncated for k in variables.keys(): if i in k: i = k break if i in extracols: extstat = 'e' # check if column already present currcolumn = ("%s_%s" % (colprefix, i)) if dbfdriver: currcolumn = currcolumn[:10] variables_dbf[currcolumn.replace("%s_" % colprefix, '')] = i colnames.append(currcolumn) if currcolumn in grass.vector_columns(vector, layer).keys(): if not flags['c']: grass.fatal( (_("Cannot create column <%s> (already present). ") % currcolumn) + _("Use -c flag to update values in this column.")) else: if i == "n": coltype = "INTEGER" else: coltype = "DOUBLE PRECISION" addcols.append(currcolumn + ' ' + coltype) if addcols: grass.verbose(_("Adding columns '%s'") % addcols) try: grass.run_command('v.db.addcolumn', map=vector, columns=addcols, layer=layer) except CalledModuleError: grass.fatal(_("Adding columns failed. Exiting.")) # calculate statistics: grass.message(_("Processing input data (%d categories)...") % number) # get rid of any earlier attempts grass.try_remove(sqltmp) f = open(sqltmp, 'w') # do the stats p = grass.pipe_command('r.univar', flags='t' + extstat, map=raster, zones=rastertmp, percentile=percentile, sep=';') first_line = 1 f.write("{0}\n".format(grass.db_begin_transaction(fi['driver']))) for line in p.stdout: if first_line: first_line = 0 continue vars = decode(line).rstrip('\r\n').split(';') f.write("UPDATE %s SET" % fi['table']) first_var = 1 for colname in colnames: variable = colname.replace("%s_" % colprefix, '', 1) if dbfdriver: variable = variables_dbf[variable] i = variables[variable] value = vars[i] # convert nan, +nan, -nan, inf, +inf, -inf, Infinity, +Infinity, # -Infinity to NULL if value.lower().endswith('nan') or 'inf' in value.lower(): value = 'NULL' if not first_var: f.write(" , ") else: first_var = 0 f.write(" %s=%s" % (colname, value)) f.write(" WHERE %s=%s;\n" % (fi['key'], vars[0])) f.write("{0}\n".format(grass.db_commit_transaction(fi['driver']))) p.wait() f.close() grass.message(_("Updating the database ...")) exitcode = 0 try: grass.run_command('db.execute', input=sqltmp, database=fi['database'], driver=fi['driver']) grass.verbose( (_("Statistics calculated from raster map <{raster}>" " and uploaded to attribute table" " of vector map <{vector}>.").format(raster=raster, vector=vector))) except CalledModuleError: grass.warning( _("Failed to upload statistics to attribute table of vector map <%s>." ) % vector) exitcode = 1 sys.exit(exitcode)
def main(): global TMPLOC, SRCGISRC, GISDBASE, TMP_REG_NAME GDALdatasource = options['input'] output = options['output'] method = options['resample'] memory = options['memory'] bands = options['band'] tgtres = options['resolution'] title = options["title"] if flags['e'] and not output: output = 'rimport_tmp' # will be removed with the entire tmp location if options['resolution_value']: if tgtres != 'value': grass.fatal( _("To set custom resolution value, select 'value' in resolution option" )) tgtres_value = float(options['resolution_value']) if tgtres_value <= 0: grass.fatal(_("Resolution value can't be smaller than 0")) elif tgtres == 'value': grass.fatal( _("Please provide the resolution for the imported dataset or change to 'estimated' resolution" )) # try r.in.gdal directly first additional_flags = 'l' if flags['l'] else '' if flags['o']: additional_flags += 'o' region_flag = '' if options['extent'] == 'region': region_flag += 'r' if flags['o'] or is_projection_matching(GDALdatasource): parameters = dict(input=GDALdatasource, output=output, memory=memory, flags='ak' + additional_flags + region_flag) if bands: parameters['band'] = bands try: grass.run_command('r.in.gdal', **parameters) grass.verbose( _("Input <%s> successfully imported without reprojection") % GDALdatasource) return 0 except CalledModuleError as e: grass.fatal( _("Unable to import GDAL dataset <%s>") % GDALdatasource) grassenv = grass.gisenv() tgtloc = grassenv['LOCATION_NAME'] # make sure target is not xy if grass.parse_command('g.proj', flags='g')['name'] == 'xy_location_unprojected': grass.fatal( _("Coordinate reference system not available for current location <%s>" ) % tgtloc) tgtmapset = grassenv['MAPSET'] GISDBASE = grassenv['GISDBASE'] TMPLOC = grass.append_node_pid("tmp_r_import_location") TMP_REG_NAME = grass.append_node_pid("tmp_r_import_region") SRCGISRC, src_env = grass.create_environment(GISDBASE, TMPLOC, 'PERMANENT') # create temp location from input without import grass.verbose( _("Creating temporary location for <%s>...") % GDALdatasource) # creating a new location with r.in.gdal requires a sanitized env env = os.environ.copy() env = grass.sanitize_mapset_environment(env) parameters = dict(input=GDALdatasource, output=output, memory=memory, flags='c', title=title, location=TMPLOC, quiet=True) if bands: parameters['band'] = bands try: grass.run_command('r.in.gdal', env=env, **parameters) except CalledModuleError: grass.fatal(_("Unable to read GDAL dataset <%s>") % GDALdatasource) # prepare to set region in temp location if 'r' in region_flag: tgtregion = TMP_REG_NAME grass.run_command('v.in.region', output=tgtregion, flags='d') # switch to temp location # print projection at verbose level grass.verbose( grass.read_command('g.proj', flags='p', env=src_env).rstrip(os.linesep)) # make sure input is not xy if grass.parse_command('g.proj', flags='g', env=src_env)['name'] == 'xy_location_unprojected': grass.fatal( _("Coordinate reference system not available for input <%s>") % GDALdatasource) # import into temp location grass.verbose( _("Importing <%s> to temporary location...") % GDALdatasource) parameters = dict(input=GDALdatasource, output=output, memory=memory, flags='ak' + additional_flags) if bands: parameters['band'] = bands if 'r' in region_flag: grass.run_command('v.proj', location=tgtloc, mapset=tgtmapset, input=tgtregion, output=tgtregion, env=src_env) grass.run_command('g.region', vector=tgtregion, env=src_env) parameters['flags'] = parameters['flags'] + region_flag try: grass.run_command('r.in.gdal', env=src_env, **parameters) except CalledModuleError: grass.fatal(_("Unable to import GDAL dataset <%s>") % GDALdatasource) outfiles = grass.list_grouped('raster', env=src_env)['PERMANENT'] # is output a group? group = False path = os.path.join(GISDBASE, TMPLOC, 'group', output) if os.path.exists(path): group = True path = os.path.join(GISDBASE, TMPLOC, 'group', output, 'POINTS') if os.path.exists(path): grass.fatal(_("Input contains GCPs, rectification is required")) if 'r' in region_flag: grass.run_command('g.remove', type="vector", flags="f", name=tgtregion, env=src_env) # switch to target location if 'r' in region_flag: grass.run_command('g.remove', type="vector", flags="f", name=tgtregion) region = grass.region() rflags = None if flags['n']: rflags = 'n' vreg = TMP_REG_NAME for outfile in outfiles: n = region['n'] s = region['s'] e = region['e'] w = region['w'] env = os.environ.copy() if options['extent'] == 'input': # r.proj -g try: tgtextents = grass.read_command('r.proj', location=TMPLOC, mapset='PERMANENT', input=outfile, flags='g', memory=memory, quiet=True) except CalledModuleError: grass.fatal(_("Unable to get reprojected map extent")) try: srcregion = grass.parse_key_val(tgtextents, val_type=float, vsep=' ') n = srcregion['n'] s = srcregion['s'] e = srcregion['e'] w = srcregion['w'] except ValueError: # import into latlong, expect 53:39:06.894826N srcregion = grass.parse_key_val(tgtextents, vsep=' ') n = grass.float_or_dms(srcregion['n'][:-1]) * \ (-1 if srcregion['n'][-1] == 'S' else 1) s = grass.float_or_dms(srcregion['s'][:-1]) * \ (-1 if srcregion['s'][-1] == 'S' else 1) e = grass.float_or_dms(srcregion['e'][:-1]) * \ (-1 if srcregion['e'][-1] == 'W' else 1) w = grass.float_or_dms(srcregion['w'][:-1]) * \ (-1 if srcregion['w'][-1] == 'W' else 1) env['GRASS_REGION'] = grass.region_env(n=n, s=s, e=e, w=w) # v.in.region in tgt grass.run_command('v.in.region', output=vreg, quiet=True, env=env) # reproject to src # switch to temp location try: grass.run_command('v.proj', input=vreg, output=vreg, location=tgtloc, mapset=tgtmapset, quiet=True, env=src_env) # test if v.proj created a valid area if grass.vector_info_topo(vreg, env=src_env)['areas'] != 1: grass.fatal(_("Please check the 'extent' parameter")) except CalledModuleError: grass.fatal(_("Unable to reproject to source location")) # set region from region vector grass.run_command('g.region', raster=outfile, env=src_env) grass.run_command('g.region', vector=vreg, env=src_env) # align to first band grass.run_command('g.region', align=outfile, env=src_env) # get number of cells cells = grass.region(env=src_env)['cells'] estres = math.sqrt((n - s) * (e - w) / cells) # remove from source location for multi bands import grass.run_command('g.remove', type='vector', name=vreg, flags='f', quiet=True, env=src_env) # switch to target location grass.run_command('g.remove', type='vector', name=vreg, flags='f', quiet=True) grass.message( _("Estimated target resolution for input band <{out}>: {res}"). format(out=outfile, res=estres)) if flags['e']: continue env = os.environ.copy() if options['extent'] == 'input': env['GRASS_REGION'] = grass.region_env(n=n, s=s, e=e, w=w) res = None if tgtres == 'estimated': res = estres elif tgtres == 'value': res = tgtres_value grass.message( _("Using given resolution for input band <{out}>: {res}"). format(out=outfile, res=res)) # align to requested resolution env['GRASS_REGION'] = grass.region_env(res=res, flags='a', env=env) else: curr_reg = grass.region() grass.message( _("Using current region resolution for input band " "<{out}>: nsres={ns}, ewres={ew}").format( out=outfile, ns=curr_reg['nsres'], ew=curr_reg['ewres'])) # r.proj grass.message(_("Reprojecting <%s>...") % outfile) try: grass.run_command('r.proj', location=TMPLOC, mapset='PERMANENT', input=outfile, method=method, resolution=res, memory=memory, flags=rflags, quiet=True, env=env) except CalledModuleError: grass.fatal(_("Unable to to reproject raster <%s>") % outfile) if grass.raster_info(outfile)['min'] is None: grass.fatal(_("The reprojected raster <%s> is empty") % outfile) if flags['e']: return 0 if group: grass.run_command('i.group', group=output, input=','.join(outfiles)) # TODO: write metadata with r.support return 0
def main(): global usermask, mapset, tmp_rmaps, tmp_vmaps input = options['input'] output = options['output'] tension = options['tension'] smooth = options['smooth'] method = options['method'] edge = int(options['edge']) segmax = int(options['segmax']) npmin = int(options['npmin']) lambda_ = float(options['lambda']) memory = options['memory'] quiet = True # FIXME mapset = grass.gisenv()['MAPSET'] unique = str(os.getpid()) # Shouldn't we use temp name? prefix = 'r_fillnulls_%s_' % unique failed_list = list( ) # a list of failed holes. Caused by issues with v.surf.rst. Connected with #1813 # check if input file exists if not grass.find_file(input)['file']: grass.fatal(_("Raster map <%s> not found") % input) # save original region reg_org = grass.region() # check if a MASK is already present # and remove it to not interfere with NULL lookup part # as we don't fill MASKed parts! if grass.find_file('MASK', mapset=mapset)['file']: usermask = "usermask_mask." + unique grass.message(_("A user raster mask (MASK) is present. Saving it...")) grass.run_command('g.rename', quiet=quiet, raster=('MASK', usermask)) # check if method is rst to use v.surf.rst if method == 'rst': # idea: filter all NULLS and grow that area(s) by 3 pixel, then # interpolate from these surrounding 3 pixel edge filling = prefix + 'filled' grass.use_temp_region() grass.run_command('g.region', align=input, quiet=quiet) region = grass.region() ns_res = region['nsres'] ew_res = region['ewres'] grass.message(_("Using RST interpolation...")) grass.message(_("Locating and isolating NULL areas...")) # creating binary (0/1) map if usermask: grass.message(_("Skipping masked raster parts")) grass.mapcalc( "$tmp1 = if(isnull(\"$input\") && !($mask == 0 || isnull($mask)),1,null())", tmp1=prefix + 'nulls', input=input, mask=usermask) else: grass.mapcalc("$tmp1 = if(isnull(\"$input\"),1,null())", tmp1=prefix + 'nulls', input=input) tmp_rmaps.append(prefix + 'nulls') # restoring user's mask, if present # to ignore MASKed original values if usermask: grass.message(_("Restoring user mask (MASK)...")) try: grass.run_command('g.rename', quiet=quiet, raster=(usermask, 'MASK')) except CalledModuleError: grass.warning(_("Failed to restore user MASK!")) usermask = None # grow identified holes by X pixels grass.message(_("Growing NULL areas")) tmp_rmaps.append(prefix + 'grown') try: grass.run_command('r.grow', input=prefix + 'nulls', radius=edge + 0.01, old=1, new=1, out=prefix + 'grown', quiet=quiet) except CalledModuleError: grass.fatal( _("abandoned. Removing temporary map, restoring " "user mask if needed:")) # assign unique IDs to each hole or hole system (holes closer than edge distance) grass.message(_("Assigning IDs to NULL areas")) tmp_rmaps.append(prefix + 'clumped') try: grass.run_command('r.clump', input=prefix + 'grown', output=prefix + 'clumped', quiet=quiet) except CalledModuleError: grass.fatal( _("abandoned. Removing temporary map, restoring " "user mask if needed:")) # get a list of unique hole cat's grass.mapcalc("$out = if(isnull($inp), null(), $clumped)", out=prefix + 'holes', inp=prefix + 'nulls', clumped=prefix + 'clumped') tmp_rmaps.append(prefix + 'holes') # use new IDs to identify holes try: grass.run_command('r.to.vect', flags='v', input=prefix + 'holes', output=prefix + 'holes', type='area', quiet=quiet) except: grass.fatal( _("abandoned. Removing temporary maps, restoring " "user mask if needed:")) tmp_vmaps.append(prefix + 'holes') # get a list of unique hole cat's cats_file_name = grass.tempfile(False) grass.run_command('v.db.select', flags='c', map=prefix + 'holes', columns='cat', file=cats_file_name, quiet=quiet) cat_list = list() cats_file = open(cats_file_name) for line in cats_file: cat_list.append(line.rstrip('\n')) cats_file.close() os.remove(cats_file_name) if len(cat_list) < 1: grass.fatal(_("Input map has no holes. Check region settings.")) # GTC Hole is NULL area in a raster map grass.message(_("Processing %d map holes") % len(cat_list)) first = True hole_n = 1 for cat in cat_list: holename = prefix + 'hole_' + cat # GTC Hole is a NULL area in a raster map grass.message(_("Filling hole %s of %s") % (hole_n, len(cat_list))) hole_n = hole_n + 1 # cut out only CAT hole for processing try: grass.run_command('v.extract', input=prefix + 'holes', output=holename + '_pol', cats=cat, quiet=quiet) except CalledModuleError: grass.fatal( _("abandoned. Removing temporary maps, restoring " "user mask if needed:")) tmp_vmaps.append(holename + '_pol') # zoom to specific hole with a buffer of two cells around the hole to # remove rest of data try: grass.run_command('g.region', vector=holename + '_pol', align=input, w='w-%d' % (edge * 2 * ew_res), e='e+%d' % (edge * 2 * ew_res), n='n+%d' % (edge * 2 * ns_res), s='s-%d' % (edge * 2 * ns_res), quiet=quiet) except CalledModuleError: grass.fatal( _("abandoned. Removing temporary maps, restoring " "user mask if needed:")) # remove temporary map to not overfill disk try: grass.run_command('g.remove', flags='fb', type='vector', name=holename + '_pol', quiet=quiet) except CalledModuleError: grass.fatal( _("abandoned. Removing temporary maps, restoring " "user mask if needed:")) tmp_vmaps.remove(holename + '_pol') # copy only data around hole grass.mapcalc("$out = if($inp == $catn, $inp, null())", out=holename, inp=prefix + 'holes', catn=cat) tmp_rmaps.append(holename) # If here loop is split into two, next part of loop can be run in parallel # (except final result patching) # Downside - on large maps such approach causes large disk usage # grow hole border to get it's edge area tmp_rmaps.append(holename + '_grown') try: grass.run_command('r.grow', input=holename, radius=edge + 0.01, old=-1, out=holename + '_grown', quiet=quiet) except CalledModuleError: grass.fatal( _("abandoned. Removing temporary map, restoring " "user mask if needed:")) # no idea why r.grow old=-1 doesn't replace existing values with NULL grass.mapcalc("$out = if($inp == -1, null(), \"$dem\")", out=holename + '_edges', inp=holename + '_grown', dem=input) tmp_rmaps.append(holename + '_edges') # convert to points for interpolation tmp_vmaps.append(holename) try: grass.run_command('r.to.vect', input=holename + '_edges', output=holename, type='point', flags='z', quiet=quiet) except CalledModuleError: grass.fatal( _("abandoned. Removing temporary maps, restoring " "user mask if needed:")) # count number of points to control segmax parameter for interpolation: pointsnumber = grass.vector_info_topo(map=holename)['points'] grass.verbose(_("Interpolating %d points") % pointsnumber) if pointsnumber < 2: grass.verbose(_("No points to interpolate")) failed_list.append(holename) continue # Avoid v.surf.rst warnings if pointsnumber < segmax: use_npmin = pointsnumber use_segmax = pointsnumber * 2 else: use_npmin = npmin use_segmax = segmax # launch v.surf.rst tmp_rmaps.append(holename + '_dem') try: grass.run_command('v.surf.rst', quiet=quiet, input=holename, elev=holename + '_dem', tension=tension, smooth=smooth, segmax=use_segmax, npmin=use_npmin) except CalledModuleError: # GTC Hole is NULL area in a raster map grass.fatal(_("Failed to fill hole %s") % cat) # v.surf.rst sometimes fails with exit code 0 # related bug #1813 if not grass.find_file(holename + '_dem')['file']: try: tmp_rmaps.remove(holename) tmp_rmaps.remove(holename + '_grown') tmp_rmaps.remove(holename + '_edges') tmp_rmaps.remove(holename + '_dem') tmp_vmaps.remove(holename) except: pass grass.warning( _("Filling has failed silently. Leaving temporary maps " "with prefix <%s> for debugging.") % holename) failed_list.append(holename) continue # append hole result to interpolated version later used to patch into original DEM if first: tmp_rmaps.append(filling) grass.run_command('g.region', align=input, raster=holename + '_dem', quiet=quiet) grass.mapcalc("$out = if(isnull($inp), null(), $dem)", out=filling, inp=holename, dem=holename + '_dem') first = False else: tmp_rmaps.append(filling + '_tmp') grass.run_command('g.region', align=input, raster=(filling, holename + '_dem'), quiet=quiet) grass.mapcalc( "$out = if(isnull($inp), if(isnull($fill), null(), $fill), $dem)", out=filling + '_tmp', inp=holename, dem=holename + '_dem', fill=filling) try: grass.run_command('g.rename', raster=(filling + '_tmp', filling), overwrite=True, quiet=quiet) except CalledModuleError: grass.fatal( _("abandoned. Removing temporary maps, restoring user " "mask if needed:")) # this map has been removed. No need for later cleanup. tmp_rmaps.remove(filling + '_tmp') # remove temporary maps to not overfill disk try: tmp_rmaps.remove(holename) tmp_rmaps.remove(holename + '_grown') tmp_rmaps.remove(holename + '_edges') tmp_rmaps.remove(holename + '_dem') except: pass try: grass.run_command('g.remove', quiet=quiet, flags='fb', type='raster', name=(holename, holename + '_grown', holename + '_edges', holename + '_dem')) except CalledModuleError: grass.fatal( _("abandoned. Removing temporary maps, restoring " "user mask if needed:")) try: tmp_vmaps.remove(holename) except: pass try: grass.run_command('g.remove', quiet=quiet, flags='fb', type='vector', name=holename) except CalledModuleError: grass.fatal( _("abandoned. Removing temporary maps, restoring user mask if needed:" )) # check if method is different from rst to use r.resamp.bspline if method != 'rst': grass.message(_("Using %s bspline interpolation") % method) # clone current region grass.use_temp_region() grass.run_command('g.region', align=input) reg = grass.region() # launch r.resamp.bspline tmp_rmaps.append(prefix + 'filled') # If there are no NULL cells, r.resamp.bslpine call # will end with an error although for our needs it's fine # Only problem - this state must be read from stderr new_env = dict(os.environ) new_env['LC_ALL'] = 'C' if usermask: try: p = grass.core.start_command('r.resamp.bspline', input=input, mask=usermask, output=prefix + 'filled', method=method, ew_step=3 * reg['ewres'], ns_step=3 * reg['nsres'], lambda_=lambda_, memory=memory, flags='n', stderr=subprocess.PIPE, env=new_env) stderr = grass.decode(p.communicate()[1]) if "No NULL cells found" in stderr: grass.run_command('g.copy', raster='%s,%sfilled' % (input, prefix), overwrite=True) p.returncode = 0 grass.warning( _("Input map <%s> has no holes. Copying to output without modification." ) % (input, )) except CalledModuleError as e: grass.fatal( _("Failure during bspline interpolation. Error message: %s" ) % stderr) else: try: p = grass.core.start_command('r.resamp.bspline', input=input, output=prefix + 'filled', method=method, ew_step=3 * reg['ewres'], ns_step=3 * reg['nsres'], lambda_=lambda_, memory=memory, flags='n', stderr=subprocess.PIPE, env=new_env) stderr = grass.decode(p.communicate()[1]) if "No NULL cells found" in stderr: grass.run_command('g.copy', raster='%s,%sfilled' % (input, prefix), overwrite=True) p.returncode = 0 grass.warning( _("Input map <%s> has no holes. Copying to output without modification." ) % (input, )) except CalledModuleError as e: grass.fatal( _("Failure during bspline interpolation. Error message: %s" ) % stderr) # restoring user's mask, if present: if usermask: grass.message(_("Restoring user mask (MASK)...")) try: grass.run_command('g.rename', quiet=quiet, raster=(usermask, 'MASK')) except CalledModuleError: grass.warning(_("Failed to restore user MASK!")) usermask = None # set region to original extents, align to input grass.run_command('g.region', n=reg_org['n'], s=reg_org['s'], e=reg_org['e'], w=reg_org['w'], align=input) # patch orig and fill map grass.message(_("Patching fill data into NULL areas...")) # we can use --o here as g.parser already checks on startup grass.run_command('r.patch', input=(input, prefix + 'filled'), output=output, overwrite=True) # restore the real region grass.del_temp_region() grass.message(_("Filled raster map is: %s") % output) # write cmd history: grass.raster_history(output) if len(failed_list) > 0: grass.warning( _("Following holes where not filled. Temporary maps with are left " "in place to allow examination of unfilled holes")) outlist = failed_list[0] for hole in failed_list[1:]: outlist = ', ' + outlist grass.message(outlist) grass.message(_("Done."))
def main(): global usermask, mapset, tmp_rmaps, tmp_vmaps input = options['input'] output = options['output'] tension = options['tension'] smooth = options['smooth'] method = options['method'] edge = int(options['edge']) segmax = int(options['segmax']) npmin = int(options['npmin']) quiet = True # FIXME mapset = grass.gisenv()['MAPSET'] unique = str(os.getpid()) # Shouldn't we use temp name? prefix = 'r_fillnulls_%s_' % unique failed_list = list() # a list of failed holes. Caused by issues with v.surf.rst. Connected with #1813 #check if input file exists if not grass.find_file(input)['file']: grass.fatal(_("Raster map <%s> not found") % input) # save original region reg_org = grass.region() # check if a MASK is already present # and remove it to not interfere with NULL lookup part # as we don't fill MASKed parts! if grass.find_file('MASK', mapset = mapset)['file']: usermask = "usermask_mask." + unique grass.message(_("A user raster mask (MASK) is present. Saving it...")) grass.run_command('g.rename', quiet = quiet, rast = ('MASK',usermask)) #check if method is rst to use v.surf.rst if method == 'rst': # idea: filter all NULLS and grow that area(s) by 3 pixel, then # interpolate from these surrounding 3 pixel edge filling = prefix + 'filled' grass.use_temp_region() grass.run_command('g.region', align = input, quiet = quiet) region = grass.region() ns_res = region['nsres'] ew_res = region['ewres'] grass.message(_("Using RST interpolation...")) grass.message(_("Locating and isolating NULL areas...")) # creating binary (0/1) map if usermask: grass.message(_("Skipping masked raster parts")) grass.mapcalc("$tmp1 = if(isnull($input) && !($mask == 0 || isnull($mask)),1,null())", tmp1 = prefix + 'nulls', input = input, mask = usermask) else: grass.mapcalc("$tmp1 = if(isnull($input),1,null())", tmp1 = prefix + 'nulls', input = input) tmp_rmaps.append(prefix + 'nulls') # restoring user's mask, if present # to ignore MASKed original values if usermask: grass.message(_("Restoring user mask (MASK)...")) if grass.run_command('g.rename', quiet = quiet, rast = (usermask, 'MASK')) != 0: grass.warning(_("Failed to restore user MASK!")) usermask = None # grow identified holes by X pixels grass.message(_("Growing NULL areas")) tmp_rmaps.append(prefix + 'grown') if grass.run_command('r.grow', input = prefix + 'nulls', radius = edge + 0.01, old = 1, new = 1, out = prefix + 'grown', quiet = quiet) != 0: grass.fatal(_("abandoned. Removing temporary map, restoring user mask if needed:")) # assign unique IDs to each hole or hole system (holes closer than edge distance) grass.message(_("Assigning IDs to NULL areas")) tmp_rmaps.append(prefix + 'clumped') if grass.run_command('r.clump', input = prefix + 'grown', output = prefix + 'clumped', quiet = quiet) != 0: grass.fatal(_("abandoned. Removing temporary map, restoring user mask if needed:")) # get a list of unique hole cat's grass.mapcalc("$out = if(isnull($inp), null(), $clumped)", out = prefix + 'holes', inp = prefix + 'nulls', clumped = prefix + 'clumped') tmp_rmaps.append(prefix + 'holes') # use new IDs to identify holes if grass.run_command('r.to.vect', flags = 'v', input = prefix + 'holes', output = prefix + 'holes', type = 'area', quiet = quiet) != 0: grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:")) tmp_vmaps.append(prefix + 'holes') # get a list of unique hole cat's cats_file_name = grass.tempfile(False) grass.run_command('v.db.select', flags = 'c', map = prefix + 'holes', columns = 'cat', file = cats_file_name, quiet = quiet) cat_list = list() cats_file = file(cats_file_name) for line in cats_file: cat_list.append(line.rstrip('\n')) cats_file.close() os.remove(cats_file_name) if len(cat_list) < 1: grass.fatal(_("Input map has no holes. Check region settings.")) # GTC Hole is NULL area in a raster map grass.message(_("Processing %d map holes") % len(cat_list)) first = True hole_n = 1 for cat in cat_list: holename = prefix + 'hole_' + cat # GTC Hole is a NULL area in a raster map grass.message(_("Filling hole %s of %s") % (hole_n, len(cat_list))) hole_n = hole_n + 1 # cut out only CAT hole for processing if grass.run_command('v.extract', input = prefix + 'holes', output = holename + '_pol', cats = cat, quiet = quiet) != 0: grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:")) tmp_vmaps.append(holename + '_pol') # zoom to specific hole with a buffer of two cells around the hole to remove rest of data if grass.run_command('g.region', vect = holename + '_pol', align = input, w = 'w-%d' % (edge * 2 * ew_res), e = 'e+%d' % (edge * 2 * ew_res), n = 'n+%d' % (edge * 2 * ns_res), s = 's-%d' % (edge * 2 * ns_res), quiet = quiet) != 0: grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:")) # remove temporary map to not overfill disk if grass.run_command('g.remove', flags = 'fb', type = 'vect', pattern = holename + '_pol', quiet = quiet) != 0: grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:")) tmp_vmaps.remove(holename + '_pol') # copy only data around hole grass.mapcalc("$out = if($inp == $catn, $inp, null())", out = holename, inp = prefix + 'holes', catn = cat) tmp_rmaps.append(holename) # If here loop is split into two, next part of loop can be run in parallel # (except final result patching) # Downside - on large maps such approach causes large disk usage # grow hole border to get it's edge area tmp_rmaps.append(holename + '_grown') if grass.run_command('r.grow', input = holename, radius = edge + 0.01, old = -1, out = holename + '_grown', quiet = quiet) != 0: grass.fatal(_("abandoned. Removing temporary map, restoring user mask if needed:")) # no idea why r.grow old=-1 doesn't replace existing values with NULL grass.mapcalc("$out = if($inp == -1, null(), $dem)", out = holename + '_edges', inp = holename + '_grown', dem = input) tmp_rmaps.append(holename + '_edges') # convert to points for interpolation tmp_vmaps.append(holename) if grass.run_command('r.to.vect', input = holename + '_edges', output = holename, type = 'point', flags = 'z', quiet = quiet) != 0: grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:")) # count number of points to control segmax parameter for interpolation: pointsnumber = grass.vector_info_topo(map = holename)['points'] grass.verbose(_("Interpolating %d points") % pointsnumber) if pointsnumber < 2: grass.verbose(_("No points to interpolate")) failed_list.append(holename) continue # Avoid v.surf.rst warnings if pointsnumber < segmax: npmin = pointsnumber + 1 segmax = pointsnumber # launch v.surf.rst tmp_rmaps.append(holename + '_dem') if grass.run_command('v.surf.rst', quiet = quiet, input = holename, elev = holename + '_dem', tension = tension, smooth = smooth, segmax = segmax, npmin = npmin) != 0: # GTC Hole is NULL area in a raster map grass.fatal(_("Failed to fill hole %s") % cat) # v.surf.rst sometimes fails with exit code 0 # related bug #1813 if not grass.find_file(holename + '_dem')['file']: try: tmp_rmaps.remove(holename) tmp_rmaps.remove(holename + '_grown') tmp_rmaps.remove(holename + '_edges') tmp_rmaps.remove(holename + '_dem') tmp_vmaps.remove(holename) except: pass grass.warning(_("Filling has failed silently. Leaving temporary maps with prefix <%s> for debugging.") % holename) failed_list.append(holename) continue # append hole result to interpolated version later used to patch into original DEM if first: tmp_rmaps.append(filling) grass.run_command('g.region', align = input, rast = holename + '_dem', quiet = quiet) grass.mapcalc("$out = if(isnull($inp), null(), $dem)", out = filling, inp = holename, dem = holename + '_dem') first = False else: tmp_rmaps.append(filling + '_tmp') grass.run_command('g.region', align = input, rast = (filling, holename + '_dem'), quiet = quiet) grass.mapcalc("$out = if(isnull($inp), if(isnull($fill), null(), $fill), $dem)", out = filling + '_tmp', inp = holename, dem = holename + '_dem', fill = filling) if grass.run_command('g.rename', rast = (filling + '_tmp', filling), overwrite = True, quiet = quiet) != 0: grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:")) tmp_rmaps.remove(filling + '_tmp') # this map has been removed. No need for later cleanup. # remove temporary maps to not overfill disk try: tmp_rmaps.remove(holename) tmp_rmaps.remove(holename + '_grown') tmp_rmaps.remove(holename + '_edges') tmp_rmaps.remove(holename + '_dem') except: pass if grass.run_command('g.remove', quiet = quiet, flags = 'fb', type = 'rast', pattern = (holename, holename + '_grown', holename + '_edges', holename + '_dem')) != 0: grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:")) try: tmp_vmaps.remove(holename) except: pass if grass.run_command('g.remove', quiet = quiet, flags = 'fb', type = 'vect', pattern = holename) != 0: grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:")) #check if method is different from rst to use r.resamp.bspline if method != 'rst': grass.message(_("Using %s bspline interpolation") % method) # clone current region grass.use_temp_region() grass.run_command('g.region', align = input) reg = grass.region() # launch r.resamp.bspline tmp_rmaps.append(prefix + 'filled') if usermask: grass.run_command('r.resamp.bspline', input = input, mask = usermask, output = prefix + 'filled', method = method, ew_step = 3 * reg['ewres'], ns_step = 3 * reg['nsres'], _lambda = 0.01, flags = 'n') else: grass.run_command('r.resamp.bspline', input = input, output = prefix + 'filled', method = method, ew_step = 3 * reg['ewres'], ns_step = 3 * reg['nsres'], _lambda = 0.01, flags = 'n') # restoring user's mask, if present: if usermask: grass.message(_("Restoring user mask (MASK)...")) if grass.run_command('g.rename', quiet = quiet, rast = (usermask, 'MASK')) != 0: grass.warning(_("Failed to restore user MASK!")) usermask = None # set region to original extents, align to input grass.run_command('g.region', n = reg_org['n'], s = reg_org['s'], e = reg_org['e'], w = reg_org['w'], align = input) # patch orig and fill map grass.message(_("Patching fill data into NULL areas...")) # we can use --o here as g.parser already checks on startup grass.run_command('r.patch', input = (input,prefix + 'filled'), output = output, overwrite = True) # restore the real region grass.del_temp_region() grass.message(_("Filled raster map is: %s") % output) # write cmd history: grass.raster_history(output) if len(failed_list) > 0: grass.warning(_("Following holes where not filled. Temporary maps with are left in place to allow examination of unfilled holes")) outlist = failed_list[0] for hole in failed_list[1:]: outlist = ', ' + outlist grass.message(outlist) grass.message(_("Done."))