Beispiel #1
0
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)
Beispiel #2
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)
Beispiel #3
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
Beispiel #4
0
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)
Beispiel #6
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:
            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."))
Beispiel #7
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:
            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
Beispiel #10
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()
Beispiel #11
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.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()
Beispiel #12
0
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
Beispiel #14
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."))
Beispiel #15
0
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)
Beispiel #16
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> 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."))
Beispiel #17
0
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.")
Beispiel #18
0
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
Beispiel #19
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
Beispiel #21
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."))
Beispiel #22
0
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
Beispiel #23
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)
Beispiel #24
0
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
Beispiel #25
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."))
Beispiel #26
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'])
    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."))