Ejemplo n.º 1
0
def main():
    map = options['map']
    layer = options['layer']
    column = options['column']
    otable = options['otable']
    ocolumn = options['ocolumn']

    f = grass.vector_layer_db(map, layer)

    maptable = f['table']
    database = f['database']
    driver = f['driver']

    if driver == 'dbf':
	grass.fatal(_("JOIN is not supported for tables stored in DBF format"))

    if not maptable:
	grass.fatal(_("There is no table connected to this map. Unable to join any column."))

    if not grass.vector_columns(map, layer).has_key(column):
	grass.fatal(_("Column <%s> not found in table <%s> at layer <%s>") % (column, map, layer))

    all_cols_ot = grass.db_describe(otable, driver = driver, database = database)['cols']
    all_cols_tt = grass.vector_columns(map, int(layer)).keys()

    select = "SELECT $colname FROM $otable WHERE $otable.$ocolumn=$table.$column"
    template = string.Template("UPDATE $table SET $colname=(%s);" % select)

    for col in all_cols_ot:
	# Skip the vector column which is used for join
	colname = col[0]
	if colname == column:
	    continue
	# Sqlite 3 does not support the precision number any more
	if len(col) > 2 and driver != "sqlite":
	    coltype = "%s(%s)" % (col[1], col[2])
	else:
	    coltype = "%s" % col[1]

	colspec = "%s %s" % (colname, coltype)

	# Add only the new column to the table
	if colname not in all_cols_tt:
	    if grass.run_command('v.db.addcolumn', map = map, columns = colspec, layer = layer) != 0:
	        grass.fatal(_("Error creating column <%s>") % colname)

	stmt = template.substitute(table = maptable, column = column,
				   otable = otable, ocolumn = ocolumn,
				   colname = colname)

        grass.verbose(_("Updating column <%s> of vector map <%s>...") % (colname, map))
	if grass.write_command('db.execute', stdin = stmt, input = '-', database = database, driver = driver) != 0:
	    grass.fatal(_("Error filling column <%s>") % colname)

    # write cmd history:
    grass.vector_history(map)
Ejemplo n.º 2
0
    def ImportMap(self, map, column):
        """ Imports GRASS map as SpatialPointsDataFrame and adds x/y columns to attribute table.
        Checks for NULL values in the provided column and exits if they are present."""

        #@NOTE: new way with R - as it doesn't alter original data
        Rpointmap = robjects.r.readVECT(map, type='point')
        # checks if x,y columns are present in dataframe. If they do are present, but with different names,
        # they'll be duplicated.
        if "x" not in robjects.r.names(Rpointmap):
            # extract coordinates with S4 method
            coordinatesPreDF = robjects.r['as.data.frame'](robjects.r.coordinates(Rpointmap))
            coordinatesDF = robjects.r['data.frame'](x=coordinatesPreDF.rx('coords.x1')[0],
                                                     y=coordinatesPreDF.rx('coords.x2')[0])
            # match coordinates with data slot of SpatialPointsDataFrame - maptools function
            # match is done on row.names
            Rpointmap = robjects.r.spCbind(Rpointmap, coordinatesDF)

        # GRASS checks for null values in the chosen column. R can hardly handle column as a variable,
        # looks for a hardcoded string.
        cols = grass.vector_columns(map=map, layer=1)
        nulls = int(grass.parse_command('v.univar',
                                        map=map,
                                        column=column,
                                        type='point',
                                        parse=(grass.parse_key_val,
                                               {'sep': ': '}
                                               )
                                        )['number of NULL attributes'])
        if nulls > 0:
            grass.fatal(
                _("%d NULL value(s) in the selected column - unable to perform kriging.") %
                nulls)
        return Rpointmap
Ejemplo n.º 3
0
    def ImportMap(self, map, column):
        """ Imports GRASS map as SpatialPointsDataFrame and adds x/y columns to attribute table.
        Checks for NULL values in the provided column and exits if they are present."""

        #@NOTE: new way with R - as it doesn't alter original data
        Rpointmap = robjects.r.readVECT6(map, type='point')
        # checks if x,y columns are present in dataframe. If they do are present, but with different names,
        # they'll be duplicated.
        if "x" not in robjects.r.names(Rpointmap):
            # extract coordinates with S4 method
            coordinatesPreDF = robjects.r['as.data.frame'](
                robjects.r.coordinates(Rpointmap))
            coordinatesDF = robjects.r['data.frame'](
                x=coordinatesPreDF.rx('coords.x1')[0],
                y=coordinatesPreDF.rx('coords.x2')[0])
            # match coordinates with data slot of SpatialPointsDataFrame - maptools function
            # match is done on row.names
            Rpointmap = robjects.r.spCbind(Rpointmap, coordinatesDF)

        # GRASS checks for null values in the chosen column. R can hardly handle column as a variable,
        # looks for a hardcoded string.
        cols = grass.vector_columns(map=map, layer=1)
        nulls = int(
            grass.parse_command('v.univar',
                                map=map,
                                column=column,
                                type='point',
                                parse=(grass.parse_key_val, {
                                    'sep': ': '
                                }))['number of NULL attributes'])
        if nulls > 0:
            grass.fatal(
                _("%d NULL value(s) in the selected column - unable to perform kriging."
                  ) % nulls)
        return Rpointmap
def extract_data(input, output, cats, value):
    if len(cats) > 20000:
        newcol = "train_val_%s" % (os.getpid())
        columns_existing = grass.vector_columns(options["input"]).keys()
        if newcol not in columns_existing:
            grass.run_command("v.db.addcolumn",
                              map=input,
                              columns="%s INTEGER" % (newcol))
        n = 500
        for i in range(0, len(cats), n):
            cats_list = cats[i:i + n]
            grass.run_command(
                "v.db.update",
                where="cat IN (%s)" % (",".join(cats_list)),
                map=input,
                column=newcol,
                value=value,
                quiet=True,
            )
            grass.percent(i + n, len(cats), 1)
        grass.run_command(
            "v.extract",
            input=input,
            output=output,
            where="%s='%d'" % (newcol, value),
        )
    else:
        grass.run_command("v.extract",
                          input=input,
                          cats=",".join(cats),
                          output=output)
Ejemplo n.º 5
0
def main():
    vector = options['map']
    layer = options['layer']
    column = options['column']
    value = options['value']
    qcolumn = options['qcolumn']
    where = options['where']

    mapset = grass.gisenv()['MAPSET']

    # does map exist in CURRENT mapset?
    if not grass.find_file(vector, element='vector', mapset=mapset)['file']:
        grass.fatal(_("Vector map <%s> not found in current mapset") % vector)

    try:
        f = grass.vector_db(vector)[int(layer)]
    except KeyError:
        grass.fatal(
            _('There is no table connected to this map. Run v.db.connect or v.db.addtable first.'
              ))

    table = f['table']
    database = f['database']
    driver = f['driver']

    # checking column types
    try:
        coltype = grass.vector_columns(vector, layer)[column]['type']
    except KeyError:
        grass.fatal(_('Column <%s> not found') % column)

    if qcolumn:
        if value:
            grass.fatal(_('<value> and <qcolumn> are mutually exclusive'))
        # special case: we copy from another column
        value = qcolumn
    else:
        if not value:
            grass.fatal(_('Either <value> or <qcolumn> must be given'))
        # we insert a value
        if coltype.upper() not in ["INTEGER", "DOUBLE PRECISION"]:
            value = "'%s'" % value

    cmd = "UPDATE %s SET %s=%s" % (table, column, value)
    if where:
        cmd += " WHERE " + where

    grass.verbose("SQL: \"%s\"" % cmd)

    grass.write_command('db.execute',
                        input='-',
                        database=database,
                        driver=driver,
                        stdin=cmd)

    # write cmd history:
    grass.vector_history(vector)

    return 0
def cleanup():
    grass.message(_("Cleaning up..."))
    if newcol:
        columns_existing = grass.vector_columns(options["input"]).keys()
        if newcol in columns_existing:
            grass.run_command("v.db.dropcolumn",
                              map=options["input"],
                              columns=newcol)
Ejemplo n.º 7
0
def main():
    options, flags = gscript.parser()
    inputmap = options['input']
    layer = options['layer']
    outputmap = options['output']
    sort_column = options['column']
    reverse = True
    if flags['r']:
        reverse = False

    columns = gscript.vector_columns(inputmap)
    key_column = gscript.vector_layer_db(inputmap, layer)['key']
    sort_index = columns[sort_column]['index']+2
    sorted_cols = sorted(iter(columns.items()), key=lambda x_y: x_y[1]['index'])
    column_def="x DOUBLE PRECISION, y DOUBLE PRECISION, cat INTEGER"
    colnames = []
    for colcount in range(1,len(sorted_cols)):
        name = sorted_cols[colcount][0]
        type = sorted_cols[colcount][1]['type']
        if name == sort_column and (type != 'INTEGER' and type != 'DOUBLE PRECISION'):
            gscript.fatal('Sort column must be numeric')
        if name == key_column:
            continue
        colnames.append(name)
        column_def += ", %s %s" % (name, type)

    inpoints=gscript.read_command('v.out.ascii',
                            in_=inputmap,
                            columns=colnames,
                            quiet=True)

    points=[]
    for line in inpoints.splitlines():
        data = [num(x) for x in line.split('|')]
        points.append(data)

    points_sorted=sorted(points, key=lambda x: x[sort_index], reverse=reverse)

    outpoints = ""
    for list in points_sorted:
        outpoints+="|".join([str(x) for x in list])+"\n"

    gscript.write_command('v.in.ascii',
                        input='-',
                        stdin=outpoints,
                        output=outputmap,
                        x=1,
                        y=2,
                        cat=3,
                        columns=column_def,
                        quiet=True)

    gscript.run_command('v.db.dropcolumn',
                        map=outputmap,
                        columns='x,y',
                        quiet=True)

    return 0
Ejemplo n.º 8
0
def main():
    global output, tmp

    input = options['input']
    output = options['output']
    layer = options['layer']
    column = options['column']

    # setup temporary file
    tmp = str(os.getpid())

    # does map exist?
    if not grass.find_file(input, element='vector')['file']:
        grass.fatal(_("Vector map <%s> not found") % input)

    if not column:
        grass.warning(
            _("No '%s' option specified. Dissolving based on category values from layer <%s>.") %
            ("column", layer))
        grass.run_command('v.extract', flags='d', input=input,
                          output=output, type='area', layer=layer)
    else:
        if int(layer) == -1:
            grass.warning(_("Invalid layer number (%d). "
                            "Parameter '%s' specified, assuming layer '1'.") %
                          (int(layer), 'column'))
            layer = '1'
        try:
            coltype = grass.vector_columns(input, layer)[column]
        except KeyError:
            grass.fatal(_('Column <%s> not found') % column)

        if coltype['type'] not in ('INTEGER', 'SMALLINT', 'CHARACTER', 'TEXT'):
            grass.fatal(_("Key column must be of type integer or string"))

        f = grass.vector_layer_db(input, layer)

        table = f['table']

        tmpfile = '%s_%s' % (output, tmp)

        try:
            grass.run_command('v.reclass', input=input, output=tmpfile,
                              layer=layer, column=column)
            grass.run_command('v.extract', flags='d', input=tmpfile,
                              output=output, type='area', layer=layer)
        except CalledModuleError as e:
            grass.fatal(_("Final extraction steps failed."
                          " Check above error messages and"
                          " see following details:\n%s") % e)

    # write cmd history:
    grass.vector_history(output)
Ejemplo n.º 9
0
def main():
    global output, tmp

    input = options['input']
    output = options['output']
    layer = options['layer']
    column = options['column']

    # setup temporary file
    tmp = str(os.getpid())

    # does map exist?
    if not grass.find_file(input, element='vector')['file']:
        grass.fatal(_("Vector map <%s> not found") % input)

    if not column:
        grass.warning(
            _("No '%s' option specified. Dissolving based on category values from layer <%s>.") %
            ("column", layer))
        grass.run_command('v.extract', flags='d', input=input,
                          output=output, type='area', layer=layer)
    else:
        if int(layer) == -1:
            grass.warning(_("Invalid layer number (%d). "
                            "Parameter '%s' specified, assuming layer '1'.") %
                          (int(layer), 'column'))
            layer = '1'
        try:
            coltype = grass.vector_columns(input, layer)[column]
        except KeyError:
            grass.fatal(_('Column <%s> not found') % column)

        if coltype['type'] not in ('INTEGER', 'SMALLINT', 'CHARACTER', 'TEXT'):
            grass.fatal(_("Key column must be of type integer or string"))

        f = grass.vector_layer_db(input, layer)

        table = f['table']

        tmpfile = '%s_%s' % (output, tmp)

        try:
            grass.run_command('v.reclass', input=input, output=tmpfile,
                              layer=layer, column=column)
            grass.run_command('v.extract', flags='d', input=tmpfile,
                              output=output, type='area', layer=layer)
        except CalledModuleError as e:
            grass.fatal(_("Final extraction steps failed."
                          " Check above error messages and"
                          " see following details:\n%s") % e)

    # write cmd history:
    grass.vector_history(output)
Ejemplo n.º 10
0
def main():
    vector = options['map']
    layer = options['layer']
    column = options['column']
    value = options['value']
    qcolumn = options['qcolumn']
    where = options['where']

    mapset = grass.gisenv()['MAPSET']

    # does map exist in CURRENT mapset?
    if not grass.find_file(vector, element = 'vector', mapset = mapset)['file']:
	grass.fatal(_("Vector map <%s> not found in current mapset") % vector)

    try:
        f = grass.vector_db(vector)[int(layer)]
    except KeyError:
	grass.fatal(_('There is no table connected to this map. Run v.db.connect or v.db.addtable first.'))

    table = f['table']
    database = f['database']
    driver = f['driver']

    # checking column types
    try:
        coltype = grass.vector_columns(vector, layer)[column]['type']
    except KeyError:
	grass.fatal(_('Column <%s> not found') % column)

    if qcolumn:
	if value:
	    grass.fatal(_('<value> and <qcolumn> are mutually exclusive'))
	# special case: we copy from another column
	value = qcolumn
    else:
	if not value:
	    grass.fatal(_('Either <value> or <qcolumn> must be given'))
	# we insert a value
	if coltype.upper() not in ["INTEGER", "DOUBLE PRECISION"]:
	    value = "'%s'" % value

    cmd = "UPDATE %s SET %s=%s" % (table, column, value)
    if where:
	cmd += " WHERE " + where

    grass.verbose("SQL: \"%s\"" % cmd)

    grass.write_command('db.execute', input = '-', database = database, driver = driver, stdin = cmd)

    # write cmd history:
    grass.vector_history(vector)

    return 0
Ejemplo n.º 11
0
    def __init__(self,**optionsandflags):
        '''Process all arguments and prepare processing'''
        # add all options and flags as attributes (only nonempty ones)
        self.options = {}
        for o in optionsandflags:
            if optionsandflags[o]!='':
                try: self.options[o] = int(optionsandflags[o])             # int
                except ValueError:
                    try: self.options[o] = float(optionsandflags[o])       # float
                    except ValueError: self.options[o] = optionsandflags[o]# str
        self.__dict__.update(self.options)
        # save region for convenience
        self.region = grass.region()

        # INPUT CHECK

        # input dir
        if not os.path.exists(self.datadir): grass.fatal('%s doesnt exisist!' %self.datadir)

        # climate stations columns
        cols=grass.vector_columns(self.climstations)
        for c in [self.fnames, self.stationelevation]:
            if c not in cols: grass.fatal('Cant find %s in table %s' %(c,self.climatestations))
        # subbasins
        if self.elevation not in grass.vector_columns(self.subbasins):
            grass.fatal('Cant find %s in table %s' %(self.elevation,self.subbasins))

        # no extension
        if 'ext' not in self.options: self.ext=''

        # check if INTERPOL.PAR can be written
        self.par = True
        parneeded = ['method','start','end','minnb','maxnb','maxdist','nodata']
        if any([e not in self.options for e in parneeded]):
            grass.warning('''Won't write INTERPOL.PAR as any of these arguments
            is not set %s''' %(parneeded,))
            self.par = False
        return
Ejemplo n.º 12
0
def main():
    options, flags = gs.parser()

    vector = options["input"]
    layer = 1
    raster = options["output"]
    method = options["method"]
    z = 3
    sep = "pipe"
    out_args = {}

    if not gs.find_file(vector, element="vector")["fullname"]:
        gs.fatal("Vector map <{0}> not found".format(vector))

    if options["column"]:
        z = 4
        out_args["column"] = options["column"]
        out_args["where"] = "{0} IS NOT NULL".format(options["column"])

        columns = gs.vector_columns(vector)

        if options["column"] not in columns:
            gs.fatal(_("Column <{0}> not found".format(options["column"])))
        if columns[options["column"]]["type"] not in ("INTEGER",
                                                      "DOUBLE PRECISION"):
            gs.fatal(_("Column <{0}> is not numeric".format(
                options["column"])))

    out_process = gs.pipe_command(
        "v.out.ascii",
        input=vector,
        layer=layer,
        format="point",
        separator=sep,
        flags="r",
        **out_args,
    )
    in_process = gs.start_command(
        "r.in.xyz",
        input="-",
        output=raster,
        method=method,
        z=z,
        separator=sep,
        stdin=out_process.stdout,
    )
    in_process.communicate()
    out_process.wait()

    return 0
Ejemplo n.º 13
0
    def __init__(self,**optionsandflags):
        '''Process all arguments and prepare processing'''
        # add all options and flags as attributes (only nonempty ones)
        self.options = {}
        for o in optionsandflags:
            if optionsandflags[o]!='': self.options[o] = optionsandflags[o]
        self.__dict__.update(self.options)
        #TODO: check if accumulation map is an int and has minus values within subbasin MASK

        # make rast from subbasin vector
        self.subbasinrast = 'subbasin__rast'
        self.nextsubb_col = 'nextID'
        self.subb_col     = 'subbasinID'

        # make sure subbasins are in current mapset
        VectMapset=self.subbasins.split('@')
        if len(VectMapset)==2 and VectMapset[1]!=grass.gisenv()['MAPSET']:
            grass.fatal('!!! %s needs to be in the current mapset because I will update its table !!!' %(self.subbasins))

        # check what columns to use
        cols = grass.vector_columns(self.subbasins)
        if 'subbasinID' not in cols and 'cat' in cols:
            grun('v.db.addcolumn',map=self.subbasins,columns=self.subb_col+' int',quiet=True)
            grun('v.db.update', map=self.subbasins, column=self.subb_col, qcol='cat')

        # make rast
        grun('v.to.rast',input=self.subbasins,output=self.subbasinrast,
                 use='attr', attrcolumn=self.subb_col,overwrite=True, quiet=True)
        # check fromto and prepare
        if 'fromto' in self.options:
            try:
                # make array
                a = np.array(self.fromto.split(','),dtype=int).reshape(-1,2)
                # add a 0 inlet column to it
                a = np.column_stack((a,np.zeros(len(a))))
                # bring into rec array
                self.fromto = np.array(zip(*a.T),dtype=[('subbasinID',int),
                                       ('nextID',int),('inletID',int)])
            except:
                grass.fatal('No integers or uneven number of values in fromto pairs. %s' %self.fromto)

        # check river course
        if 'rivercourse' in self.options:
            if type(self.rivercourse)==str:
                self.rivercourse = map(int,self.rivercourse.split(','))
            elif type(self.rivercourse)==int:
                self.rivercourse = [self.rivercourse]

        return
Ejemplo n.º 14
0
def main():
    map = options['map']
    layer = options['layer']
    columns = options['columns']
    columns = [col.strip() for col in columns.split(',')]

    # does map exist in CURRENT mapset?
    mapset = grass.gisenv()['MAPSET']
    exists = bool(
        grass.find_file(map, element='vector', mapset=mapset)['file'])

    if not exists:
        grass.fatal(_("Vector map <%s> not found in current mapset") % map)

    try:
        f = grass.vector_db(map)[int(layer)]
    except KeyError:
        grass.fatal(
            _("There is no table connected to this map. Run v.db.connect or v.db.addtable first."
              ))

    table = f['table']
    database = f['database']
    driver = f['driver']
    column_existing = grass.vector_columns(map, int(layer)).keys()

    for col in columns:
        if not col:
            grass.fatal(
                _("There is an empty column. Did you leave a trailing comma?"))
        col_name = col.split(' ')[0].strip()
        if col_name in column_existing:
            grass.error(
                _("Column <%s> is already in the table. Skipping.") % col_name)
            continue
        grass.verbose(_("Adding column <%s> to the table") % col_name)
        p = grass.feed_command('db.execute',
                               input='-',
                               database=database,
                               driver=driver)
        res = "ALTER TABLE {} ADD COLUMN {}".format(table, col)
        p.stdin.write(encode(res))
        grass.debug(res)
        p.stdin.close()
        if p.wait() != 0:
            grass.fatal(_("Unable to add column <%s>.") % col)

    # write cmd history:
    grass.vector_history(map)
Ejemplo n.º 15
0
def create_river_network(invect, outvect):
	"""
	Prepare the input river network vector by:
	possibly smoothing the line, and
	adding several columns to the vector attribute table.
	THe added columns include start and end points for output to HEC-RAS
	"""	

	thresh = options['threshold']
	layer = options['layer']
	
	if (flags['s']):
		# Perform smoothing of the input vector	
		grass.run_command('v.generalize', input=invect, output=outvect, _method='snakes',
			threshold=thresh, overwrite=True, quiet=True)
	
	# Add a reach length column to the river vector
	# First check if column exists
	columns_exist = grass.vector_columns(outvect, int(layer)).keys()
	if not "reach_len" in columns_exist:
		grass.run_command('v.db.addcolumn', map=outvect, columns="reach_len DOUBLE PRECISION", quiet=True)
	# Also add columns for start and end point of each reach
	if not "start_x" in columns_exist:
		grass.run_command('v.db.addcolumn', map=outvect, columns="start_x DOUBLE PRECISION", quiet=True)
	if not "start_y" in columns_exist:
		grass.run_command('v.db.addcolumn', map=outvect, columns="start_y DOUBLE PRECISION", quiet=True)
	if not "start_elev" in columns_exist:
		grass.run_command('v.db.addcolumn', map=outvect, columns="start_elev DOUBLE PRECISION", quiet=True)
	if not "end_x" in columns_exist:
		grass.run_command('v.db.addcolumn', map=outvect, columns="end_x DOUBLE PRECISION", quiet=True)
	if not "end_y" in columns_exist:
		grass.run_command('v.db.addcolumn', map=outvect, columns="end_y DOUBLE PRECISION", quiet=True)
	if not "end_elev" in columns_exist:
		grass.run_command('v.db.addcolumn', map=outvect, columns="end_elev DOUBLE PRECISION", quiet=True)
	# Now update those columns
	grass.run_command('v.to.db',map=outvect, option="length", columns="reach_len", quiet=True)
	grass.run_command('v.to.db',map=outvect, option="start", columns="start_x,start_y",quiet=True)
	grass.run_command('v.to.db',map=outvect, option="end", columns="end_x,end_y", quiet=True)
	d=grass.read_command('v.db.select',map=outvect, separator="=", columns="cat,reach_len", flags="c")

	# Initialize dict of reach categories with their lengths
	# Each key in the dictionary is the cat of a river reach
	# each value is the length of that reach
	reach_cats=grass.parse_key_val(d, val_type=float)

	return reach_cats
Ejemplo n.º 16
0
def main():
    map = options['map']
    layer = options['layer']
    columns = options['columns']
    columns = [col.strip() for col in columns.split(',')]

    # does map exist in CURRENT mapset?
    mapset = grass.gisenv()['MAPSET']
    exists = bool(grass.find_file(map, element='vector', mapset=mapset)['file'])

    if not exists:
        grass.fatal(_("Vector map <%s> not found in current mapset") % map)

    try:
        f = grass.vector_db(map)[int(layer)]
    except KeyError:
        grass.fatal(
            _("There is no table connected to this map. Run v.db.connect or v.db.addtable first."))

    table = f['table']
    database = f['database']
    driver = f['driver']
    column_existing = grass.vector_columns(map, int(layer)).keys()

    for col in columns:
        if not col:
            grass.fatal(_("There is an empty column. Did you leave a trailing comma?"))
        col_name = col.split(' ')[0].strip()
        if col_name in column_existing:
            grass.error(_("Column <%s> is already in the table. Skipping.") % col_name)
            continue
        grass.verbose(_("Adding column <%s> to the table") % col_name)
        p = grass.feed_command('db.execute', input='-', database=database, driver=driver)
        p.stdin.write("ALTER TABLE %s ADD COLUMN %s" % (table, col))
        grass.debug("ALTER TABLE %s ADD COLUMN %s" % (table, col))
        p.stdin.close()
        if p.wait() != 0:
            grass.fatal(_("Unable to add column <%s>.") % col)

    # write cmd history:
    grass.vector_history(map)
Ejemplo n.º 17
0
def main():
    global output, tmp

    input = options['input']
    output = options['output']
    layer = options['layer']
    column = options['column']

    #### setup temporary file
    tmp = str(os.getpid())

    # does map exist?
    if not grass.find_file(input, element = 'vector')['file']:
	grass.fatal(_("Vector map <%s> not found") % input)
    
    if not column:
	grass.run_command('v.extract', flags = 'd', input = input,
			  output = output, type = 'area', layer = layer)
    else:
        try:
            coltype = grass.vector_columns(input, layer)[column]
        except KeyError:
            grass.fatal(_('Column <%s> not found') % column)
        
	if coltype['type'] not in ('INTEGER', 'CHARACTER'):
	    grass.fatal(_("Key column must be of type integer or string"))

        f = grass.vector_layer_db(input, layer)

	table = f['table']

	tmpfile = '%s_%s' % (output, tmp)

	if grass.run_command('v.reclass', input = input, output = tmpfile,
                             layer = layer, column = column) == 0:
            grass.run_command('v.extract', flags = 'd', input = tmpfile,
                              output = output, type = 'area', layer = layer)

    # write cmd history:
    grass.vector_history(output)
Ejemplo n.º 18
0
def main():
    options, flags = gs.parser()

    vector = options['input']
    layer = 1
    raster = options['output']
    method = options['method']
    z = 3
    sep = 'pipe'
    out_args = {}

    if not gs.find_file(vector, element='vector')['fullname']:
        gs.fatal('Vector map <{0}> not found'.format(vector))

    if options['column']:
        z = 4
        out_args['column'] = options['column']
        out_args['where'] = '{0} IS NOT NULL'.format(options['column'])

        columns = gs.vector_columns(vector)

        if options['column'] not in columns:
            gs.fatal(_('Column <{0}> not found'.format(options['column'])))
        if columns[options['column']]['type'] not in ('INTEGER', 'DOUBLE PRECISION'):
            gs.fatal(_('Column <{0}> is not numeric'.format(options['column'])))


    out_process = gs.pipe_command(
        'v.out.ascii', input=vector, layer=layer, format='point',
        separator=sep, flags='r', **out_args)
    in_process = gs.start_command(
        'r.in.xyz', input='-', output=raster, method=method, z=z,
        separator=sep, stdin=out_process.stdout)
    in_process.communicate()
    out_process.wait()

    return 0
Ejemplo n.º 19
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
Ejemplo n.º 20
0
def set_up_columns(vector, layer, percentile, colprefix, basecols, dbfdriver,
                   c):
    """Get columns-depending variables and create columns, if needed.

    :param vector: name of vector map or data source for direct OGR access
    :param layer: layer number or name
    :param percentile: percentile to calculate
    :param colprefix: column prefix for new attribute columns
    :param basecols: the methods to use
    :param dbfdriver: boolean saying if the driver is dbf
    :param c: boolean saying if it should continue if upload column(s) already
        exist
    :return: colprefix, variables_dbf, variables, colnames, extstat
    """
    # 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
    variables_dbf = {}

    if dbfdriver:
        colprefix = colprefix[:6]

    # 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': 3,
        '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 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."))

    return colprefix, variables_dbf, variables, colnames, extstat
Ejemplo n.º 21
0
def main():
    global tmp, tmpname, rastertmp1, rastertmp2, rastertmp3
    rastertmp1 = False
    rastertmp2 = False
    rastertmp3 = False

    #### setup temporary files
    tmp = grass.tempfile()
    # we need a random name
    tmpname = grass.basename(tmp)

    vector = options["vector"]
    layer = options["layer"]
    column = options["column"]
    weight = options["weight"]
    output = options["output"]

    # vector exists?
    result = grass.find_file(vector, element="vector")
    if len(result["name"]) == 0:
        grass.fatal(_("Input vector <%s> not found") % vector)

    # raster exists?
    result = grass.find_file(weight, element="cell")
    if len(result["name"]) == 0:
        grass.fatal(_("Input weight raster <%s> not found") % weight)

    # column exists ?
    if column not in grass.vector_columns(vector, layer).keys():
        grass.fatal(
            _("Column does not exist for vector <%s>, layer %s") %
            (vector, layer))

    # is column numeric?
    coltype = grass.vector_columns(vector, layer)[column]["type"]

    if coltype not in ("INTEGER", "DOUBLE PRECISION"):
        grass.fatal(_("Column must be numeric"))

    # rasterize with cats (will be base layer)
    # strip off mapset for tmp output
    vector_basename = vector.split("@")[0]
    rastertmp1 = "%s_%s_1" % (vector_basename, tmpname)
    try:
        grass.run_command("v.to.rast",
                          input=vector,
                          output=rastertmp1,
                          use="cat",
                          quiet=True)
    except CalledModuleError:
        grass.fatal(_("An error occurred while converting vector to raster"))

    # rasterize with column
    rastertmp2 = "%s_%s_2" % (vector_basename, tmpname)
    try:
        grass.run_command(
            "v.to.rast",
            input=vector,
            output=rastertmp2,
            use="attr",
            layer=layer,
            attrcolumn=column,
            quiet=True,
        )
    except CalledModuleError:
        grass.fatal(_("An error occurred while converting vector to raster"))

    # zonal statistics
    rastertmp3 = "%s_%s_3" % (vector_basename, tmpname)
    try:
        grass.run_command(
            "r.stats.zonal",
            base=rastertmp1,
            cover=weight,
            method="sum",
            output=rastertmp3,
            quiet=True,
        )
    except CalledModuleError:
        grass.fatal(_("An error occurred while calculating zonal statistics"))

    # weighted interpolation
    exp = "$output = if($sumweight == 0, if(isnull($area_val), null(), 0), double($area_val) * $weight / $sumweight)"

    grass.mapcalc(exp,
                  output=output,
                  sumweight=rastertmp3,
                  area_val=rastertmp2,
                  weight=weight)

    sys.exit(0)
Ejemplo n.º 22
0
def main():
    if flags['r'] and flags['s']:
	grass.fatal(_("Either -r or -s flag"))

    mapname = options['map']
    option = options['option']
    layer = options['layer']
    units = options['units']

    nuldev = file(os.devnull, 'w')

    if not grass.find_file(mapname, 'vector')['file']:
	grass.fatal(_("Vector map '%s' not found in mapset search path.") % mapname)

    colnames = grass.vector_columns(mapname, layer, getDict = False, stderr = nuldev)
    if not colnames:
	colnames = ['cat']

    if option == 'coor':
	columns = ['dummy1','dummy2','dummy3']
	extracolnames = ['x','y','z']
    else:
	columns = ['dummy1']
	extracolnames = [option]

    if units in ['p','percent']:
	unitsp = 'meters'
    elif units:
	unitsp = units
    else:
	unitsp = None

    # NOTE: we suppress -1 cat and 0 cat

    if colnames:
	p = grass.pipe_command('v.db.select', quiet = True, flags='c', map = mapname, layer = layer)
	records1 = []
	for line in p.stdout:
	    cols = line.rstrip('\r\n').split('|')
	    if cols[0] == '0':
		continue
	    records1.append([int(cols[0])] + cols[1:])
	p.wait()
        if p.returncode != 0:
            sys.exit(1)
        
	records1.sort()

	if len(records1) == 0:
            try:
                f = grass.vector_db(map = mapname)[int(layer)]
                grass.fatal(_("There is a table connected to input vector map '%s', but"
                              "there are no categories present in the key column '%s'. Consider using"
                              "v.to.db to correct this.") % (mapname, f['key']))
            except KeyError:
                pass

	#fetch the requested attribute sorted by cat:
	p = grass.pipe_command('v.to.db', flags = 'p',
                               quiet = True,
			       map = mapname, option = option, columns = columns,
			       layer = layer, units = unitsp)
	records2 = []
	for line in p.stdout:
	    fields = line.rstrip('\r\n').split('|')
	    if fields[0] in ['cat', '-1', '0']:
		continue
	    records2.append([int(fields[0])] + fields[1:])
	p.wait()
	records2.sort()

	#make pre-table
	records3 = [r1 + r2[1:] for r1, r2 in zip(records1, records2)]
    else:
	records1 = []
        p = grass.pipe_command('v.category', inp = mapname, layer = layer, option = 'print')
	for line in p.stdout:
	    field = int(line.rstrip())
	    if field > 0:
		records1.append(field)
	p.wait()
	records1.sort()
	records1 = uniq(records1)

        #make pre-table
	p = grass.pipe_command('v.to.db', flags = 'p',
			       map = mapname, option = option, columns = columns,
			       layer = layer, units = unitsp)
	records3 = []
	for line in p.stdout:
	    fields = line.split('|')
	    if fields[0] in ['cat', '-1', '0']:
		continue
	    records3.append([int(fields[0])] + fields[1:])
	p.wait()
	records3.sort()

    # print table header
    sys.stdout.write('|'.join(colnames + extracolnames) + '\n')

    #make and print the table:
    numcols = len(colnames) + len(extracolnames)

    # calculate percents if requested
    if units != '' and units in ['p','percent']:
	# calculate total area value
	areatot = 0
	for r in records3:
	    areatot += float(r[-1])

	# calculate area percentages
	records4 = [float(r[-1]) * 100 / areatot for r in records3]
	records3 = [r1 + [r4] for r1, r4 in zip(records1, records4)]

    if flags['s']:
	# sort
	records3.sort(key = lambda r: (r[0], r[-1]))
    elif flags['r']:
	# reverse sort
	records3.sort(key = lambda r: (r[0], r[-1]), reverse = True)

    for r in records3:
	sys.stdout.write('|'.join(map(str,r)) + '\n')
Ejemplo n.º 23
0
def main():
    map = options['map']
    layer = options['layer']
    columns = options['columns'].split(',')

    mapset = grass.gisenv()['MAPSET']

    # does map exist in CURRENT mapset?
    if not grass.find_file(map, element='vector', mapset=mapset)['file']:
        grass.fatal(_("Vector map <%s> not found in current mapset") % map)

    f = grass.vector_layer_db(map, layer)

    table = f['table']
    keycol = f['key']
    database = f['database']
    driver = f['driver']

    if not table:
        grass.fatal(_("There is no table connected to the input vector map. "
                      "Unable to delete any column. Exiting."))

    if keycol in columns:
        grass.fatal(_("Unable to delete <%s> column as it is needed to keep table <%s> "
                      "connected to the input vector map <%s>") %
                    (keycol, table, map))

    for column in columns:
        if column not in grass.vector_columns(map, layer):
            grass.warning(_("Column <%s> not found in table <%s>. Skipped") % (column, table))
            continue

        if driver == "sqlite":
            # echo "Using special trick for SQLite"
            # http://www.sqlite.org/faq.html#q11
            colnames = []
            coltypes = []
            for f in grass.db_describe(table, database=database, driver=driver)['cols']:
                if f[0] == column:
                    continue
                colnames.append(f[0])
                coltypes.append("%s %s" % (f[0], f[1]))

            colnames = ", ".join(colnames)
            coltypes = ", ".join(coltypes)

            cmds = [
                "BEGIN TRANSACTION",
                "CREATE TEMPORARY TABLE ${table}_backup(${coldef})",
                "INSERT INTO ${table}_backup SELECT ${colnames} FROM ${table}",
                "DROP TABLE ${table}",
                "CREATE TABLE ${table}(${coldef})",
                "INSERT INTO ${table} SELECT ${colnames} FROM ${table}_backup",
                "CREATE UNIQUE INDEX ${table}_cat ON ${table} (${keycol} )",
                "DROP TABLE ${table}_backup",
                "COMMIT"
            ]
            tmpl = string.Template(';\n'.join(cmds))
            sql = tmpl.substitute(table=table, coldef=coltypes, colnames=colnames, keycol=keycol)
        else:
            sql = "ALTER TABLE %s DROP COLUMN %s" % (table, column)

        try:
            grass.write_command('db.execute', input='-', database=database, driver=driver,
                                stdin=sql)
        except CalledModuleError:
            grass.fatal(_("Deleting column failed"))

    # write cmd history:
    grass.vector_history(map)
Ejemplo n.º 24
0
def main():
    options, flags = gscript.parser()
    inputmap = options["input"]
    layer = options["layer"]
    outputmap = options["output"]
    sort_column = options["column"]
    reverse = True
    if flags["r"]:
        reverse = False

    columns = gscript.vector_columns(inputmap)
    key_column = gscript.vector_layer_db(inputmap, layer)["key"]
    sort_index = columns[sort_column]["index"] + 2
    sorted_cols = sorted(iter(columns.items()),
                         key=lambda x_y: x_y[1]["index"])
    column_def = "x DOUBLE PRECISION, y DOUBLE PRECISION, cat INTEGER"
    colnames = []
    for colcount in range(1, len(sorted_cols)):
        name = sorted_cols[colcount][0]
        type = sorted_cols[colcount][1]["type"]
        if name == sort_column and (type != "INTEGER"
                                    and type != "DOUBLE PRECISION"):
            gscript.fatal("Sort column must be numeric")
        if name == key_column:
            continue
        colnames.append(name)
        column_def += ", %s %s" % (name, type)

    inpoints = gscript.read_command("v.out.ascii",
                                    in_=inputmap,
                                    columns=colnames,
                                    quiet=True)

    points = []
    for line in inpoints.splitlines():
        data = [num(x) for x in line.split("|")]
        points.append(data)

    points_sorted = sorted(points,
                           key=lambda x: x[sort_index],
                           reverse=reverse)

    outpoints = ""
    for list in points_sorted:
        outpoints += "|".join([str(x) for x in list]) + "\n"

    gscript.write_command(
        "v.in.ascii",
        input="-",
        stdin=outpoints,
        output=outputmap,
        x=1,
        y=2,
        cat=3,
        columns=column_def,
        quiet=True,
    )

    gscript.run_command("v.db.dropcolumn",
                        map=outputmap,
                        columns="x,y",
                        quiet=True)

    return 0
Ejemplo n.º 25
0
def main():
    options, flags = gs.parser()

    points_name = options["points"]
    points_layer = options["points_layer"]
    points_columns = []
    if options["points_columns"]:
        points_columns = options["points_columns"].split(",")

    # TODO: Add check points exist before we query the metadata.

    input_vector_columns = gs.vector_columns(points_name, points_layer)

    if not points_columns:
        # Get all numeric columns from the table.
        # Get only the names ordered in the same as in the database.
        all_column_names = gs.vector_columns(points_name,
                                             points_layer,
                                             getDict=False)
        for name in all_column_names:
            # TODO: Find out what is the key column (usually cat) and skip it.
            column_type = input_vector_columns[name]["type"]
            if sql_type_is_numeric(column_type):
                points_columns.append(name)
    else:
        # Check the user provided columns.
        for name in points_columns:
            try:
                column_info = input_vector_columns[name]
            except KeyError:
                gs.fatal(
                    _("Column <{name}> not found in vector map <{points_name}>,"
                      " layer <{points_layer}>").format(**locals()))
            column_type = column_info["type"]
            if not sql_type_is_numeric(column_type):
                gs.fatal(
                    _("Column <{name}> in <{points_name}> is {column_type}"
                      " which is not a numeric type").format(**locals()))

    methods = options["method"].split(",")
    stats_columns_names = []
    num_new_columns = len(points_columns) * len(methods)
    if options["stats_columns"]:
        stats_columns_names = options["stats_columns"].split(",")
        names_provided = len(stats_columns_names)
        if names_provided != num_new_columns:
            gs.fatal(
                _("Number of provided stats_columns ({names_provided})"
                  " does not correspond to number of names needed"
                  " for every combination of points_columns and methods"
                  " ({num_points_columns} * {num_methods} = {names_needed})").
                format(
                    names_provided=names_provided,
                    num_points_columns=len(points_columns),
                    num_methods=len(methods),
                    names_needed=num_new_columns,
                ))
        num_unique_names = len(set(stats_columns_names))
        if names_provided != num_unique_names:
            gs.fatal(
                _("Names in stats_columns are not unique"
                  " ({names_provided} items provied"
                  " but only {num_unique_names} are unique)").format(
                      names_provided=names_provided,
                      num_unique_names=num_unique_names,
                  ))

    modified_options = options.copy()
    # Remove options we are handling here.
    del modified_options["points_columns"]
    del modified_options["stats_columns"]
    del modified_options["method"]

    # Note that the count_column is mandatory for v.vect.stats,
    # so it is simply computed more than once. Ideally, it would
    # be optional for this module which would probably mean better handling of
    # number of point and n in statistions in v.vect.stats (unless we simply
    # use temporary name and drop the column at the end).

    # The product function advances the rightmost element on every iteration,
    # so first we get all methods for one column. This is important to
    # the user if stats_columns is provided.
    for i, (points_column,
            method) in enumerate(product(points_columns, methods)):
        if stats_columns_names:
            stats_column_name = stats_columns_names[i]
        else:
            stats_column_name = f"{points_column}_{method}"
        gs.run_command(
            "v.vect.stats",
            method=method,
            points_column=points_column,
            stats_column=stats_column_name,
            quiet=True,
            **modified_options,
            errors="exit",
        )
        gs.percent(i, num_new_columns, 1)
    gs.percent(1, 1, 1)

    return 0
Ejemplo n.º 26
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)
Ejemplo n.º 27
0
def main():
    vector = options["map"]
    layer = options["layer"]
    column = options["column"]
    value = options["value"]
    qcolumn = options["query_column"]
    where = options["where"]
    sqlitefile = options["sqliteextra"]

    mapset = grass.gisenv()["MAPSET"]

    # does map exist in CURRENT mapset?
    if not grass.find_file(vector, element="vector", mapset=mapset)["file"]:
        grass.fatal(_("Vector map <%s> not found in current mapset") % vector)

    try:
        f = grass.vector_db(vector)[int(layer)]
    except KeyError:
        grass.fatal(_("There is no table connected to this map. Run v.db.connect or v.db.addtable first."))

    table = f["table"]
    database = f["database"]
    driver = f["driver"]

    # check for SQLite backend for extra functions
    if sqlitefile and driver != "sqlite":
        grass.fatal(_("Use of libsqlitefunctions only with SQLite backend"))
    if driver == "sqlite" and sqlitefile:
        if not os.access(sqlitefile, os.R_OK):
            grass.fatal(_("File <%s> not found") % sqlitefile)

    # checking column types
    try:
        coltype = grass.vector_columns(vector, layer)[column]["type"]
    except KeyError:
        grass.fatal(_("Column <%s> not found") % column)

    if qcolumn:
        if value:
            grass.fatal(_("<value> and <qcolumn> are mutually exclusive"))
        # special case: we copy from another column
        value = qcolumn
    else:
        if not value:
            grass.fatal(_("Either <value> or <qcolumn> must be given"))
        # we insert a value
        if coltype.upper() not in ["INTEGER", "DOUBLE PRECISION"]:
            value = "'%s'" % value

    cmd = "UPDATE %s SET %s=%s" % (table, column, value)
    if where:
        cmd += " WHERE " + where

    # SQLite: preload extra functions from extension lib if provided by user
    if sqlitefile:
        sqliteload = "SELECT load_extension('%s');\n" % sqlitefile
        cmd = sqliteload + cmd

    grass.verbose('SQL: "%s"' % cmd)
    grass.write_command("db.execute", input="-", database=database, driver=driver, stdin=cmd)

    # write cmd history:
    grass.vector_history(vector)

    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
Ejemplo n.º 29
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 = file(os.devnull, 'w')

    raster = options['raster']
    colprefix = options['column_prefix']
    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)

    vector = vs[0]

    rastertmp = "%s_%s" % (vector, tmpname)

    # 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=raster)

    grass.message(_("Preprocessing input data..."))
    try:
        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:
        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 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']

    # 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, '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 = file(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("{}\n".format(grass.db_begin_transaction(fi['driver'])))
    for line in p.stdout:
        if first_line:
            first_line = 0
            continue

        vars = 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("{}\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)
Ejemplo n.º 30
0
def main():
    map = options['map']
    layer = options['layer']
    column = options['column']
    otable = options['otable']
    ocolumn = options['ocolumn']
    if options['scolumns']:
        scolumns = options['scolumns'].split(',')
    else:
        scolumns = None
    
    f = grass.vector_layer_db(map, layer)

    maptable = f['table']
    database = f['database']
    driver   = f['driver']

    if driver == 'dbf':
	grass.fatal(_("JOIN is not supported for tables stored in DBF format"))

    if not maptable:
	grass.fatal(_("There is no table connected to this map. Unable to join any column."))

    # check if column is in map table
    if not grass.vector_columns(map, layer).has_key(column):
	grass.fatal(_("Column <%s> not found in table <%s>") % (column, maptable))

    # describe other table
    all_cols_ot = grass.db_describe(otable, driver = driver, database = database)['cols']

    # check if ocolumn is on other table
    if ocolumn not in [ocol[0] for ocol in all_cols_ot]:
	grass.fatal(_("Column <%s> not found in table <%s>") % (ocolumn, otable))

    # determine columns subset from other table
    if not scolumns:
        # select all columns from other table
        cols_to_add = all_cols_ot
    else:
        cols_to_add = []
    	# check if scolumns exists in the other table
    	for scol in scolumns:
            found = False
            for col_ot in all_cols_ot:
                if scol == col_ot[0]:
                    found = True
                    cols_to_add.append(col_ot)
                    break
            if not found:
                grass.warning(_("Column <%s> not found in table <%s>.") % (scol, otable))
    
    all_cols_tt = grass.vector_columns(map, int(layer)).keys()

    select = "SELECT $colname FROM $otable WHERE $otable.$ocolumn=$table.$column"
    template = string.Template("UPDATE $table SET $colname=(%s);" % select)

    for col in cols_to_add:
	# skip the vector column which is used for join
	colname = col[0]
	if colname == column:
	    continue
	# Sqlite 3 does not support the precision number any more
	if len(col) > 2 and driver != "sqlite":
	    coltype = "%s(%s)" % (col[1], col[2])
	else:
	    coltype = "%s" % col[1]

	colspec = "%s %s" % (colname, coltype)

	# add only the new column to the table
	if colname not in all_cols_tt:
	    if grass.run_command('v.db.addcolumn', map = map, columns = colspec, layer = layer) != 0:
	        grass.fatal(_("Error creating column <%s>") % colname)

	stmt = template.substitute(table = maptable, column = column,
				   otable = otable, ocolumn = ocolumn,
				   colname = colname)
        grass.debug(stmt, 1)
        grass.verbose(_("Updating column <%s> of vector map <%s>...") % (colname, map))
	if grass.write_command('db.execute', stdin = stmt, input = '-', database = database, driver = driver) != 0:
	    grass.fatal(_("Error filling column <%s>") % colname)

    # write cmd history
    grass.vector_history(map)

    return 0
Ejemplo n.º 31
0
def main():
    vector = options['map']
    layer = options['layer']
    column = options['column']
    value = options['value']
    qcolumn = options['query_column']
    where = options['where']
    sqlitefile = options['sqliteextra']

    mapset = grass.gisenv()['MAPSET']

    # does map exist in CURRENT mapset?
    if not grass.find_file(vector, element='vector', mapset=mapset)['file']:
        grass.fatal(_("Vector map <%s> not found in current mapset") % vector)

    try:
        f = grass.vector_db(vector)[int(layer)]
    except KeyError:
        grass.fatal(
            _('There is no table connected to this map. Run v.db.connect or v.db.addtable first.'
              ))

    table = f['table']
    database = f['database']
    driver = f['driver']

    # check for SQLite backend for extra functions
    if sqlitefile and driver != "sqlite":
        grass.fatal(_("Use of libsqlitefunctions only with SQLite backend"))
    if driver == "sqlite" and sqlitefile:
        if not os.access(sqlitefile, os.R_OK):
            grass.fatal(_("File <%s> not found") % sqlitefile)

    # checking column types
    try:
        coltype = grass.vector_columns(vector, layer)[column]['type']
    except KeyError:
        grass.fatal(_('Column <%s> not found') % column)

    if qcolumn:
        if value:
            grass.fatal(_('<value> and <qcolumn> are mutually exclusive'))
        # special case: we copy from another column
        value = qcolumn
    else:
        if not value:
            grass.fatal(_('Either <value> or <qcolumn> must be given'))
        # we insert a value
        if coltype.upper() not in ["INTEGER", "DOUBLE PRECISION"]:
            value = "'%s'" % value

    cmd = "UPDATE %s SET %s=%s" % (table, column, value)
    if where:
        cmd += " WHERE " + where

    # SQLite: preload extra functions from extension lib if provided by user
    if sqlitefile:
        sqliteload = "SELECT load_extension('%s');\n" % sqlitefile
        cmd = sqliteload + cmd

    grass.verbose("SQL: \"%s\"" % cmd)
    grass.write_command('db.execute',
                        input='-',
                        database=database,
                        driver=driver,
                        stdin=cmd)

    # write cmd history:
    grass.vector_history(vector)

    return 0
Ejemplo n.º 32
0
def main():
    global output, tmp

    input = options["input"]
    output = options["output"]
    layer = options["layer"]
    column = options["column"]

    # setup temporary file
    tmp = str(os.getpid())

    # does map exist?
    if not grass.find_file(input, element="vector")["file"]:
        grass.fatal(_("Vector map <%s> not found") % input)

    if not column:
        grass.warning(
            _("No '%s' option specified. Dissolving based on category values from layer <%s>."
              ) % ("column", layer))
        grass.run_command("v.extract",
                          flags="d",
                          input=input,
                          output=output,
                          type="area",
                          layer=layer)
    else:
        if int(layer) == -1:
            grass.warning(
                _("Invalid layer number (%d). "
                  "Parameter '%s' specified, assuming layer '1'.") %
                (int(layer), "column"))
            layer = "1"
        try:
            coltype = grass.vector_columns(input, layer)[column]
        except KeyError:
            grass.fatal(_("Column <%s> not found") % column)

        if coltype["type"] not in ("INTEGER", "SMALLINT", "CHARACTER", "TEXT"):
            grass.fatal(_("Key column must be of type integer or string"))

        f = grass.vector_layer_db(input, layer)

        table = f["table"]

        tmpfile = "%s_%s" % (output, tmp)

        try:
            grass.run_command("v.reclass",
                              input=input,
                              output=tmpfile,
                              layer=layer,
                              column=column)
            grass.run_command(
                "v.extract",
                flags="d",
                input=tmpfile,
                output=output,
                type="area",
                layer=layer,
            )
        except CalledModuleError as e:
            grass.fatal(
                _("Final extraction steps failed."
                  " Check above error messages and"
                  " see following details:\n%s") % e)

    # write cmd history:
    grass.vector_history(output)
Ejemplo n.º 33
0
def main():
    """Process command line parameters and update the table"""
    options, flags = gs.parser()

    vector = options["map"]
    layer = options["layer"]
    where = options["where"]
    column = options["column"]
    expression = options["expression"]
    condition = options["condition"]
    functions_file = options["functions"]

    # Map needs to be in the current mapset
    mapset = gs.gisenv()["MAPSET"]
    if not gs.find_file(vector, element="vector", mapset=mapset)["file"]:
        gs.fatal(
            _("Vector map <{vector}> does not exist or is not in the current mapset"
              "(<{mapset}>) and therefore it cannot be modified").format(
                  **locals()))

    # Map+layer needs to have a table connected
    try:
        # TODO: Support @OGR vector maps? Probably not supported by db.execute anyway.
        db_info = gs.vector_db(vector)[int(layer)]
    except KeyError:
        gs.fatal(
            _("There is no table connected to map <{vector}> (layer <{layer}>)."
              " Use v.db.connect or v.db.addtable to add it.").format(
                  **locals()))
    table = db_info["table"]
    database = db_info["database"]
    driver = db_info["driver"]
    columns = gs.vector_columns(vector, layer)

    # Check that column exists
    try:
        column_info = columns[column]
    except KeyError:
        gs.fatal(
            _("Column <{column}> not found. Use v.db.addcolumn to create it.").
            format(column=column))
    column_type = column_info["type"]

    # Check that optional function file exists
    if functions_file:
        if not os.access(functions_file, os.R_OK):
            gs.fatal(_("File <{file}> not found").format(file=functions_file))

    # Define Python functions
    # Here we need the full-deal eval and exec functions and can't sue less
    # general alternatives such as ast.literal_eval.
    def expression_function(**kwargs):
        return eval(expression, globals(), kwargs)  # pylint: disable=eval-used

    def condition_function(**kwargs):
        return eval(condition, globals(), kwargs)  # pylint: disable=eval-used

    # TODO: Add error handling for failed imports.
    if options["packages"]:
        packages = options["packages"].split(",")
        for package in packages:
            # pylint: disable=exec-used
            exec(f"import {package}", globals(), globals())
            if flags["s"]:
                exec(f"from {package} import *", globals(), globals())

    # TODO: Add error handling for invalid syntax.
    if functions_file:
        with open(functions_file) as file:
            exec(file.read(), globals(), globals())  # pylint: disable=exec-used

    # Get table contents
    if not where:
        # The condition needs to be None, an empty string is passed through.
        where = None
    if gs.version()["version"] < "7.9":
        sep = "|"  # Only one char sep for Python csv package.
        null = "NULL"
        csv_text = gs.read_command(
            "v.db.select",
            map=vector,
            layer=layer,
            separator=sep,
            null=null,
            where=where,
        )
        table_contents = csv_loads(csv_text, delimeter=sep, null=null)
    else:
        # TODO: XXX is a workaround for a bug in v.db.select -j
        json_text = gs.read_command("v.db.select",
                                    map=vector,
                                    layer=layer,
                                    flags="j",
                                    null="XXX",
                                    where=where)
        table_contents = json.loads(json_text)

    cmd = python_to_transaction(
        table=table,
        table_contents=table_contents,
        column=column,
        column_type=column_type,
        expression=expression,
        expression_function=expression_function,
        condition=condition,
        condition_function=condition_function,
        ensure_lowercase=not flags["u"],
    )

    # Messages
    if len(cmd) == 2:
        gs.message(
            "No rows to update. Try a different SQL where or Python condition."
        )
    elif len(cmd) > 2:
        # First and last statement
        gs.verbose(f'Using SQL: "{cmd[1]}...{cmd[-2]}"')

    # The newline is needed for successful execution/reading of many statements.
    # TODO: Add error handling when there is a syntax error due to wrongly
    # generated SQL statement and/or sanitize the value in update more.
    gs.write_command("db.execute",
                     input="-",
                     database=database,
                     driver=driver,
                     stdin="\n".join(cmd))

    gs.vector_history(vector)
Ejemplo n.º 34
0
def main():
    # Get the options
    input = options["input"]
    timestamp_column = options["timestamp_column"]
    columns = options["column"]
    layer = options["layer"]
    where = options["where"]
    strds = options["strds"]
    tempwhere = options["t_where"]
    i_flag = flags["i"]

    if where == "" or where == " " or where == "\n":
        where = None

    # overwrite = grass.overwrite()

    # Set verbosity level
    # quiet = True
    # if grass.verbosity() > 2:
    #     quiet = False

    grass.warning(_('This addon is experimental!'))

    # Check DB connection for input vector map
    dbcon = grass.vector_layer_db(input, layer)
    # Check the number of sample strds and the number of columns
    strds_names = strds.split(",")
    column_names = columns.split(",")
    if not len(column_names) == len(strds_names):
        grass.fatal(_('Number of columns and number of STRDS does not match.'))

    # Check type of timestamp column
    cols = grass.vector_columns(input, layer=layer)
    if timestamp_column not in cols.keys():
        grass.fatal(
            _('Could not find column {} \
                    in table connected to vector map {} \
                    at layer {}'.format(timestamp_column, input, layer)))
    if cols[timestamp_column]['type'] != 'DATE':
        if dbcon['driver'] != 'sqlite':
            # Note that SQLite does not have a DATE datatype and
            # and an index does not significantly speedup the process
            # (at least not with a couple of 100 points)
            grass.warning(
                _('Timestamp column is of type {}. \
                            It is recommended to use DATE type with an index. \
                            '.format(cols[timestamp_column]['type'])))

    # Make sure the temporal database exists
    tgis.init()
    # We need a database interface
    dbif = tgis.SQLDatabaseInterfaceConnection()
    dbif.connect()

    # Limit temporal extent to extent of points if no tempwhere is given
    if not tempwhere:
        extent = []
        for stat in ('min', 'max'):
            tsql = "SELECT {}({}) FROM {}".format(stat, timestamp_column,
                                                  dbcon['table'])
            extent.append(grass.read_command('db.select', flags='c', sql=tsql))

        grass.verbose(
            _('Temporal extent of vector points map is \
                      {} to {}'.format(extent[0], extent[1])))
    else:
        tempwhere = '({}) AND '.format(tempwhere)

    # Loop over STRDS
    counter = 0
    for strds_name in strds_names:

        cur_strds = tgis.open_old_stds(strds_name, "strds", dbif)

        granu = cur_strds.get_granularity()
        start_time = tgis.datetime_math.check_datetime_string(extent[0])
        start_gran = tgis.datetime_math.adjust_datetime_to_granularity(
            start_time, granu).isoformat()
        tempwhere += "(end_time > '{}' and start_time <= '{}')".format(
            start_gran, extent[1])  # needs to be set properly

        # Get info on registered maps in STRDS
        rows = cur_strds.get_registered_maps("name,mapset,start_time,end_time",
                                             tempwhere, "start_time", dbif)

        # Check temporal type and
        # define sampling function to use
        # becomes relevant when temporal type relative gets implemented
        if cur_strds.is_time_relative():
            grass.fatal(
                _('Sorry, STRDS of relative temporal type is not (yet) supported'
                  ))
            sample = sample_relative
        else:
            sample = sample_absolute

        # Check if there are raster maps to sample from that fullfill
        # temporal conditions
        if not rows and not tempwhere:
            dbif.close()
            grass.fatal(
                _("Space time raster dataset <%s> is empty".format(
                    cur_strds.get_id())))
        elif not rows and tempwhere:
            dbif.close()
            grass.fatal(
                _("No maps selected from Space time raster dataset <%s>, \
                          or dataset is empty".format(cur_strds.get_id())))

        # Include temporal condition into where clause
        where_clause = '({}) AND '.format(where) if where else ''

        # Loop over registered maps in STRDS
        row_number = 0
        for row in rows:
            # If r.what had a where option, r.what could be used to
            # collect raster values (without interpolation)
            # in a ParallelModuleQueue to collect values using multiple
            # cores and then upload results in one operation

            sample(input, layer, timestamp_column, column_names[counter], row,
                   where_clause, i_flag)

            row_number += 1
            grass.percent(row_number, len(rows), 3)
        counter = counter + 1

    dbif.close()
    grass.vector_history(input)
Ejemplo n.º 35
0
def main():
    mapname = options['map']
    option = options['option']
    layer = options['layer']
    units = options['units']

    nuldev = file(os.devnull, 'w')

    if not grass.find_file(mapname, 'vector')['file']:
        grass.fatal(_("Vector map <%s> not found") % mapname)

    colnames = grass.vector_columns(mapname,
                                    layer,
                                    getDict=False,
                                    stderr=nuldev)
    if not colnames:
        colnames = ['cat']

    if option == 'coor':
        columns = ['dummy1', 'dummy2', 'dummy3']
        extracolnames = ['x', 'y', 'z']
    else:
        columns = ['dummy1']
        extracolnames = [option]

    if units in ['p', 'percent']:
        unitsp = 'meters'
    elif units:
        unitsp = units
    else:
        unitsp = None

    # NOTE: we suppress -1 cat and 0 cat
    if colnames:
        p = grass.pipe_command('v.db.select',
                               quiet=True,
                               flags='c',
                               map=mapname,
                               layer=layer)
        records1 = []
        for line in p.stdout:
            cols = line.rstrip('\r\n').split('|')
            if cols[0] == '0':
                continue
            records1.append([int(cols[0])] + cols[1:])
        p.wait()
        if p.returncode != 0:
            sys.exit(1)

        records1.sort()

        if len(records1) == 0:
            try:
                f = grass.vector_db(map=mapname)[int(layer)]
                grass.fatal(
                    _("There is a table connected to input vector map '%s', but"
                      "there are no categories present in the key column '%s'. Consider using"
                      "v.to.db to correct this.") % (mapname, f['key']))
            except KeyError:
                pass

        #fetch the requested attribute sorted by cat:
        p = grass.pipe_command('v.to.db',
                               flags='p',
                               quiet=True,
                               map=mapname,
                               option=option,
                               columns=columns,
                               layer=layer,
                               units=unitsp)
        records2 = []
        for line in p.stdout:
            fields = line.rstrip('\r\n').split('|')
            if fields[0] in ['cat', '-1', '0']:
                continue
            records2.append([int(fields[0])] + fields[1:-1] +
                            [float(fields[-1])])
        p.wait()
        records2.sort()

        #make pre-table
        # len(records1) may not be the same as len(records2) because
        # v.db.select can return attributes that are not linked to features.
        records3 = []
        for r2 in records2:
            records3.append(
                filter(lambda r1: r1[0] == r2[0], records1)[0] + r2[1:])
    else:
        records1 = []
        p = grass.pipe_command('v.category',
                               inp=mapname,
                               layer=layer,
                               option='print')
        for line in p.stdout:
            field = int(line.rstrip())
            if field > 0:
                records1.append(field)
        p.wait()
        records1.sort()
        records1 = uniq(records1)

        #make pre-table
        p = grass.pipe_command('v.to.db',
                               flags='p',
                               map=mapname,
                               option=option,
                               columns=columns,
                               layer=layer,
                               units=unitsp)
        records3 = []
        for line in p.stdout:
            fields = line.split('|')
            if fields[0] in ['cat', '-1', '0']:
                continue
            records3.append([int(fields[0])] + fields[1:])
        p.wait()
        records3.sort()

    # print table header
    sys.stdout.write('|'.join(colnames + extracolnames) + '\n')

    #make and print the table:
    numcols = len(colnames) + len(extracolnames)

    # calculate percents if requested
    if units != '' and units in ['p', 'percent']:
        # calculate total area value
        areatot = 0
        for r in records3:
            areatot += float(r[-1])

        # calculate area percentages
        records4 = [float(r[-1]) * 100 / areatot for r in records3]
        records3 = [r1 + [r4] for r1, r4 in zip(records1, records4)]

    # sort results
    if options['sort']:
        if options['sort'] == 'asc':
            records3.sort(key=lambda r: r[-1])
        else:
            records3.sort(key=lambda r: r[-1], reverse=True)

    for r in records3:
        sys.stdout.write('|'.join(map(str, r)) + '\n')
Ejemplo n.º 36
0
def main():
    global tmp_graph, tmp_group, tmp_psmap, tmp_psleg, tmp_gisleg

    breakpoints = options['breakpoints']
    colorscheme = options['colorscheme']
    column = options['column']
    endcolor = options['endcolor']
    group = options['group']
    layer = options['layer']
    linecolor = options['linecolor']
    map = options['map']
    maxsize = options['maxsize']
    monitor = options['monitor']
    nint = options['nint']
    pointcolor = options['pointcolor']
    psmap = options['psmap']
    size = options['size']
    startcolor = options['startcolor']
    themecalc = options['themecalc']
    themetype = options['themetype']
    type = options['type']
    where = options['where']
    icon = options['icon']

    flag_f = flags['f']
    flag_g = flags['g']
    flag_l = flags['l']
    flag_m = flags['m']
    flag_s = flags['s']
    flag_u = flags['u']

    layer = int(layer)
    nint = int(nint)
    size = float(size)
    maxsize = float(maxsize)

    # check column type
    inf = grass.vector_columns(map, layer)
    if column not in inf:
        grass.fatal(_("No such column <%s>") % column)
    coltype = inf[column]['type'].lower()

    if coltype not in ["integer", "double precision"]:
        grass.fatal(
            _("Column <%s> is of type <%s> which is not numeric.") %
            (column, coltype))

    # create temporary file to hold d.graph commands for legend
    tmp_graph = grass.tempfile()
    # Create temporary file to commands for GIS Manager group
    tmp_group = grass.tempfile()
    # Create temporary file for commands for ps.map map file
    tmp_psmap = grass.tempfile()
    # Create temporary file for commands for ps.map legend file
    tmp_psleg = grass.tempfile()
    # create file to hold elements for GIS Manager legend
    tmp_gisleg = grass.tempfile()

    # Set display variables for group
    atype = int(type == "area")
    ptype = int(type == "point")
    ctype = int(type == "centroid")
    ltype = int(type == "line")
    btype = int(type == "boundary")

    # if running in the GUI, do not create a graphic legend in an xmon
    if flag_s:
        flag_l = False
        # if running in GUI, turn off immediate mode rendering so that the
        # iterated d.vect commands will composite using the display driver
        os.environ['GRASS_PNG_READ'] = 'TRUE'
        os.environ['GRASS_PNG_AUTO_WRITE'] = 'FALSE'

    db = grass.vector_db(map)[1]
    if not db or not db['table']:
        grass.fatal(
            _("No table connected or layer <%s> does not exist.") % layer)
    table = db['table']
    database = db['database']
    driver = db['driver']

    # update color values to the table?
    if flag_u:
        # test, if the column GRASSRGB is in the table
        s = grass.read_command('db.columns',
                               table=table,
                               database=database,
                               driver=driver)
        if 'grassrgb' not in s.splitlines():
            msg(locals(), _("Creating column 'grassrgb' in table <$table>"))
            sql = "ALTER TABLE %s ADD COLUMN grassrgb varchar(11)" % table
            grass.write_command('db.execute',
                                database=database,
                                driver=driver,
                                stdin=sql)

    # Group name
    if not group:
        group = "themes"

    f_group = file(tmp_group, 'w')
    f_group.write("Group %s\n" % group)

    # Calculate statistics for thematic intervals
    if type == "line":
        stype = "line"
    else:
        stype = ["point", "centroid"]

    if not where:
        where = None

    stats = grass.read_command('v.univar',
                               flags='eg',
                               map=map,
                               type=stype,
                               column=column,
                               where=where,
                               layer=layer)
    stats = grass.parse_key_val(stats)

    min = float(stats['min'])
    max = float(stats['max'])
    mean = float(stats['mean'])
    sd = float(stats['population_stddev'])
    q1 = float(stats['first_quartile'])
    q2 = float(stats['median'])
    q3 = float(stats['third_quartile'])
    q4 = max

    ptsize = size

    if breakpoints and themecalc != "custom_breaks":
        grass.warning(
            _("Custom breakpoints ignored due to themecalc setting."))

    # set interval for each thematic map calculation type
    if themecalc == "interval":
        numint = nint
        step = float(max - min) / numint
        breakpoints = [min + i * step for i in xrange(numint + 1)]
        annotations = ""
    elif themecalc == "std_deviation":
        # 2 standard deviation units on either side of mean,
        # plus min to -2 sd units and +2 sd units to max, if applicable
        breakpoints = [min] + [
            i for i in [(mean + i * sd)
                        for i in [-2, -1, 0, 1, 2]] if min < i < max
        ] + [max]
        annotations = [""] + [("%dsd" % i)
                              for (i, j) in [(i, mean + i * sd)
                                             for i in [-2, -1, 0, 1, 2]]
                              if (min < j < max)] + [""]
        annotations = ";".join(annotations)
        numint = len(breakpoints) - 1
    elif themecalc == "quartiles":
        numint = 4
        # one for each quartile
        breakpoints = [min, q1, q2, q3, max]
        annotations = " %f; %f; %f; %f" % (q1, q2, q3, q4)
    elif themecalc == "custom_breaks":
        if not breakpoints:
            breakpoints = sys.stdin.read()
        breakpoints = [int(x) for x in breakpoints.split()]
        numint = len(breakpoints) - 1
        annotations = ""
    else:
        grass.fatal(_("Unknown themecalc type <%s>") % themecalc)

    pointstep = (maxsize - ptsize) / (numint - 1)

    # Prepare legend cuts for too large numint
    if numint > max_leg_items:
        xupper = int(numint - max_leg_items / 2) + 1
        xlower = int(max_leg_items / 2) + 1
    else:
        xupper = 0
        xlower = 0

    # legend title
    f_graph = file(tmp_graph, 'w')
    out(
        f_graph, locals(), """\
color 0:0:0
size 2 2
move 1 95
text Thematic map legend for column $column of map $map
size 1.5 1.8
move 4 90
text Value range: $min - $max
""")

    f_gisleg = file(tmp_gisleg, 'w')
    out(
        f_gisleg, locals(), """\
title - - - {Thematic map legend for column $column of map $map}
""")

    f_psleg = file(tmp_psleg, 'w')
    out(
        f_psleg, locals(), """\
text 1% 95% Thematic map legend for column $column of map $map
  ref bottom left
end
text 4% 90% Value range: $min - $max
  ref bottom left
end
""")

    msg(locals(), _("Thematic map legend for column $column of map $map"))
    msg(locals(), _("Value range: $min - $max"))

    colorschemes = {
        "blue-red": ("0:0:255", "255:0:0"),
        "red-blue": ("255:0:0", "0:0:255"),
        "green-red": ("0:255:0", "255:0:0"),
        "red-green": ("255:0:0", "0:255:0"),
        "blue-green": ("0:0:255", "0:255:0"),
        "green-blue": ("0:255:0", "0:0:255"),
        "cyan-yellow": ("0:255:255", "255:255:0"),
        "yellow-cyan": ("255:255:0", "0:255:255"),
        "custom_gradient": (startcolor, endcolor)
    }

    # open file for psmap instructions
    f_psmap = file(tmp_psmap, 'w')

    # graduated color thematic mapping
    if themetype == "graduated_colors":
        if colorscheme in colorschemes:
            startc, endc = colorschemes[colorscheme]
        # set color schemes for graduated color maps
        elif colorscheme == "single_color":
            if themetype == "graduated_points":
                startc = endc = linecolor
            else:
                startc = endc = pointcolor
        else:
            grass.fatal(
                _("This should not happen: parser error. Unknown color scheme %s"
                  ) % colorscheme)

        color = __builtins__.map(int, startc.split(":"))
        endcolor = __builtins__.map(int, endc.split(":"))

        #The number of color steps is one less then the number of classes
        nclrstep = numint - 1
        clrstep = [(a - b) / nclrstep for a, b in zip(color, endcolor)]

        themecolor = startc

        # display graduated color themes
        if themecalc == "interval":
            out(f_graph, locals(), """\
move 4 87
text Mapped by $numint intervals of $step
""")

            out(
                f_gisleg, locals(), """\
subtitle - - - {Mapped by $numint intervals of $step}
""")

            out(
                f_psleg, locals(), """\
text 4% 87% Mapped by $numint intervals of $step
  ref bottom left
end
""")

            msg(locals(), _("Mapped by $numint intervals of $step"))

        # display graduated color themes for standard deviation units
        if themecalc == "std_deviation":
            out(
                f_graph, locals(), """\
move 4 87
text Mapped by standard deviation units of $sd (mean = $mean)
""")

            out(
                f_gisleg, locals(), """\
subtitle - - - {Mapped by standard deviation units of $sd (mean = $mean)}
""")

            out(
                f_psleg, locals(), """\
text 4% 87% Mapped by standard deviation units of $sd (mean = $mean)
  ref bottom left
end
""")

            msg(locals(),
                _("Mapped by standard deviation units of $sd (mean = $mean)"))

        # display graduated color themes for quartiles
        if themecalc == "quartiles":
            out(f_graph, locals(), """\
move 4 87
text Mapped by quartiles (median = $q2)
""")

            out(f_gisleg, locals(), """\
subtitle - - - {Mapped by quartiles (median = $q2)}
""")

            out(
                f_psleg, locals(), """\
text 4% 87% Mapped by quartiles (median = $q2)
  ref bottom left
end
""")

            msg(locals(), _("Mapped by quartiles (median = $q2)"))

        f_graph.write("""\
move 4 83
text Color
move 14 83
text Value
move 4 80
text =====
move 14 80
text ============
""")

        f_psleg.write("""\
text 4% 83% Color
  ref bottom left
end
text 14% 83% Value
  ref bottom left
end
text 4% 80% =====
  ref bottom left
end
text 14% 80% ============
  ref bottom left
end
""")

        sys.stdout.write("Color(R:G:B)\tValue\n")
        sys.stdout.write("============\t==========\n")

        line1 = 78
        line2 = 76
        line3 = 75

        i = 1
        first = True

        while i < numint:
            if flag_m:
                # math notation
                if first:
                    closebracket = "]"
                    openbracket = "["
                    mincomparison = ">="
                    first = False
                else:
                    closebracket = "]"
                    openbracket = "]"
                    mincomparison = ">"
            else:
                closebracket = ""
                openbracket = ""
                if first:
                    mincomparison = ">="
                    first = False
                else:
                    mincomparison = ">"

            themecolor = ":".join(__builtins__.map(str, color))
            if flag_f:
                linecolor = "none"
            else:
                if type in ["line", "boundary"]:
                    linecolor = themecolor
                else:
                    linecolor = linecolor

            rangemin = __builtins__.min(breakpoints)
            rangemax = __builtins__.max(breakpoints)

            if not annotations:
                extranote = ""
            else:
                extranote = annotations[i]

            if i < xlower or i >= xupper:
                xline1 = line2 + 2
                xline3 = line2 - 1
                out(
                    f_graph, locals(), """\
color $themecolor
polygon
5 $xline1
8 $xline1
8 $xline3
5 $xline3
color $linecolor
move 5 $xline1
draw 8 $xline1
draw 8 $xline3
draw 5 $xline3
draw 5 $xline1
move 14 $line2
color 0:0:0
text $openbracket$rangemin - $rangemax$closebracket $extranote
""")
            else:
                if i == xlower:
                    out(f_graph, locals(), """\
color 0:0:0
move 10 $line2
text ...
""")
                else:
                    #undo next increment
                    line2 += 4

            if i < xlower or i >= xupper:
                out(
                    f_gisleg, locals(), """\
area $themecolor $linecolor - {$openbracket$rangemin - $rangemax$closebracket $extranote}
""")

                if type in ["line", "boundary"]:
                    out(
                        f_psleg, locals(), """\
line 5% $xline1% 8% $xline1%
  color $linecolor
end
text 14% $xline1% $openbracket$rangemin - $rangemax$closebracket $extranote
  ref center left
end
""")
                elif type in ["point", "centroid"]:
                    out(
                        f_psleg, locals(), """\
point 8% $xline1%
  color $linecolor
  fcolor $themecolor
  size $size
  symbol $icon
end
text 14% $xline1% $openbracket$rangemin - $rangemax$closebracket $extranote
  ref center left
end
""")
                else:
                    out(
                        f_psleg, locals(), """\
rectangle 5% $xline1% 8% $xline3%
  color 0:0:0
  fcolor $themecolor
end
text 14% $xline3% $openbracket$rangemin - $rangemax$closebracket DCADCA $extranote
  ref bottom left
end
""")
            else:
                if i == xlower:
                    out(
                        f_psleg, locals(), """\
color 0:0:0
text 14% $xline3% ...
  ref bottom left
end
""")

                f_gisleg.write("text - - - {...}\n")

            sys.stdout.write(
                subs(
                    locals(),
                    "$themecolor\t\t$openbracket$rangemin - $rangemax$closebracket $extranote\n"
                ))
            if not where:
                sqlwhere = subs(
                    locals(),
                    "$column $mincomparison $rangemin AND $column <= $rangemax"
                )
            else:
                sqlwhere = subs(
                    locals(),
                    "$column $mincomparison $rangemin AND $column <= $rangemax AND $where"
                )

            # update color to database?
            if flag_u:
                sql = subs(
                    locals(),
                    "UPDATE $table SET GRASSRGB = '$themecolor' WHERE $sqlwhere"
                )
                grass.write_command('db.execute',
                                    database=database,
                                    driver=driver,
                                    stdin=sql)

            # Create group for GIS Manager
            if flag_g:
                # change rgb colors to hex
                xthemecolor = "#%02X%02X%02X" % tuple(
                    __builtins__.map(int, themecolor.split(":")))
                #xlinecolor=`echo $linecolor | awk -F: '{printf("#%02X%02X%02X\n",$1,$2,$3)}'`

                if "$linecolor" == "black":
                    xlinecolor = "#000000"
                else:
                    xlinecolor = xthemecolor

                # create group entry
                out(
                    f_group, locals(), """\
  _check 1
  Vector $column = $rangemin - $rangemax
    _check 1
    map $map
    display_shape 1
    display_cat 0
    display_topo 0
    display_dir 0
    display_attr 0
    type_point $ptype
    type_line $ltype
    type_boundary $btype
    type_centroid $ctype
    type_area $atype
    type_face 0
    color $xlinecolor
    fcolor $xthemecolor
    width $ptsize
    _use_fcolor 1
    lcolor #000000
    sqlcolor 0
    icon $icon
    size $ptsize
    field $layer
    lfield $layer
    attribute
    xref left
    yref center
    lsize 8
    cat
    where $sqlwhere
    _query_text 0
    _query_edit 1
    _use_where 1
    minreg
    maxreg
    _width 0.1
  End
""")

            # display theme vector map

            grass.run_command('d.vect',
                              map=map,
                              type=type,
                              layer=layer,
                              where=sqlwhere,
                              color=linecolor,
                              fcolor=themecolor,
                              icon=icon,
                              size=ptsize)

            if type in ["line", "boundary"]:
                out(
                    f_psmap, locals(), """\
vlines $map
  type $type
  layer $layer
  where $sqlwhere
  color $linecolor
  label $rangemin - $rangemax
end
""")
            elif type in ["point", "centroid"]:
                out(
                    f_psmap, locals(), """\
vpoints $map
  type $type
  layer $layer
  where $sqlwhere
  color $linecolor
  fcolor $themecolor
  symbol $icon
  label $rangemin - $rangemax
end
""")
            else:
                out(
                    f_psmap, locals(), """\
vareas $map
  layer $layer
  where $sqlwhere
  color $linecolor
  fcolor $themecolor
  label $rangemin - $rangemax
end
""")

            # increment for next theme
            i += 1
            if i == numint:
                color = endcolor
            else:
                color = [a - b for a, b in zip(color, clrstep)]
            line1 -= 4
            line2 -= 4
            line3 -= 4

    #graduated points and line widths thematic mapping

    if themetype in ["graduated_points", "graduated_lines"]:

        #display graduated points/lines by intervals
        if themecalc == "interval":
            out(f_graph, locals(), """\
move 4 87
text Mapped by $numint intervals of $step
""")

            out(
                f_gisleg, locals(), """\
subtitle - - - {Mapped by $numint intervals of $step}
""")

            out(
                f_psleg, locals(), """\
text 4% 87% Mapped by $numint intervals of $step
  ref bottom left
end
""")

            msg(locals(), _("Mapped by $numint intervals of $step"))

        # display graduated points/lines for standard deviation units
        if themecalc == "std_deviation":

            out(
                f_graph, locals(), """\
move 4 87
text Mapped by standard deviation units of $sd (mean = $mean)
""")

            out(
                f_gisleg, locals(), """\
subtitle - - - {Mapped by standard deviation units of $sd (mean = $mean)}
""")

            out(
                f_psleg, locals(), """\
text 4% 87% Mapped by standard deviation units of $sd (mean = $mean)
  ref bottom left
end
""")

            msg(locals(),
                _("Mapped by standard deviation units of $sd (mean = $mean)"))

        # display graduated points/lines for quartiles
        if themecalc == "quartiles":

            out(f_graph, locals(), """\
move 4 87
text Mapped by quartiles (median = $q2)
""")

            out(f_gisleg, locals(), """\
subtitle - - - {Mapped by quartiles (median = $q2)}
""")

            out(
                f_psleg, locals(), """\
text 4% 87% Mapped by quartiles (median = $q2)
  ref bottom left
end
""")

            msg(locals(), _("Mapped by quartiles (median = $q2)"))

        line1 = 76
        line2 = 75

        out(
            f_graph, locals(), """\
move 4 83
text Size/width
move 25 83
text Value
move 4 80
text ==============
move 25 80
text ==============
""")

        out(
            f_psleg, locals(), """\
text 4% 83% Icon size
  ref bottom left
end
text 25% 83% Value
  ref bottom left
end
text 4% 80% ============
  ref bottom left
end
text 25% 80% ============
  ref bottom left
end
""")

        sys.stdout.write("Size/width\tValue\n")
        sys.stdout.write("==========\t=====\n")

        themecolor = pointcolor

        if flag_f:
            linecolor = "none"

        i = numint
        ptsize = maxsize

        while i >= 1:
            if flag_m:
                # math notation
                if i == 1:
                    closebracket = "]"
                    openbracket = "["
                    mincomparison = ">="
                else:
                    closebracket = "]"
                    openbracket = "]"
                    mincomparison = ">"
            else:
                closebracket = ""
                openbracket = ""
                if i == 1:
                    mincomparison = ">="
                else:
                    mincomparison = ">"

            themecolor = pointcolor

            if flag_f:
                linecolor = "none"

            rangemin = __builtins__.min(breakpoints)
            rangemax = __builtins__.max(breakpoints)

            if not annotations:
                extranote = ""
            else:
                extranote = annotations[i]

            iconsize = int(ptsize / 2)
            lineht = int(ptsize / 4)
            if lineht < 4:
                lineht = 4

            if i < xlower or i >= xupper:
                if themetype == "graduated_lines":
                    out(f_graph, locals(), """\
color $linecolor
""")

                    out(
                        f_gisleg, locals(), """\
line $themecolor $linecolor $ptsize {$openbracket$rangemin - $rangemax$closebracket $extranote}
""")
                else:
                    out(f_graph, locals(), """\
color $themecolor
""")
                    out(
                        f_gisleg, locals(), """\
point $themecolor $linecolor $ptsize {$openbracket$rangemin - $rangemax$closebracket $extranote}
""")

                out(
                    f_graph, locals(), """\
icon + $iconsize 5 $line1
color 0:0:0
move 10 $line2
text $ptsize pts
move 25 $line2
text $openbracket$rangemin - $rangemax$closebracket $extranote
""")
            else:
                if i == xlower:
                    out(f_graph, locals(), """\
color 0:0:0
move 10 $line2
text ...
""")

                    out(f_gisleg, locals(), """\
text - - - ...
""")
                else:
                    # undo future line increment
                    line2 += lineht

            if i < xlower or i >= xupper:
                out(
                    f_psleg, locals(), """\
point 8% $line1%
  color $linecolor
  fcolor $themecolor
  size $iconsize
  symbol $icon
end
text 25% $line1% $openbracket$rangemin - $rangemax$closebracket $extranote
  ref center left
end
""")
            else:
                if i == xlower:
                    out(f_psleg, locals(), """\
text 25% $xline1% ...
   ref center left
end
""")

            sys.stdout.write(
                subs(
                    locals(),
                    "$ptsize\t\t$openbracket$rangemin - $rangemax$closebracket $extranote\n"
                ))

            if not where:
                sqlwhere = subs(
                    locals(),
                    "$column $mincomparison $rangemin AND $column <= $rangemax"
                )
            else:
                sqlwhere = subs(
                    locals(),
                    "$column $mincomparison $rangemin AND $column <= $rangemax AND $where"
                )

            # update color to database?
            if flag_u:
                sql = subs(
                    locals(),
                    "UPDATE $table SET grassrgb = '$themecolor' WHERE $sqlwhere"
                )
                grass.write_command('db.execute',
                                    database=database,
                                    driver=driver,
                                    stdin=sql)

            # Create group for GIS Manager
            if flag_g:
                # change rgb colors to hex
                xthemecolor = "#%02X%02X%02X" % tuple(
                    __builtins__.map(int, themecolor.split(":")))
                xlinecolor = "#000000"

                # create group entry
                out(
                    f_group, locals(), """\
  _check 1
  Vector $column = $rangemin - $rangemax
    _check 1
    map $map
    display_shape 1
    display_cat 0
    display_topo 0
    display_dir 0
    display_attr 0
    type_point $ptype
    type_line $ltype
    type_boundary $btype
    type_centroid $ctype
    type_area $atype
    type_face 0
    color $xlinecolor
    width $ptsize
    fcolor $xthemecolor
    _use_fcolor 1
    lcolor #000000
    sqlcolor 0
    icon $icon
    size $ptsize
    field $layer
    lfield $layer
    attribute
    xref left
    yref center
    lsize 8
    cat
    where $sqlwhere
    _query_text 0
    _query_edit 1
    _use_where 1
    minreg
    maxreg
    _width 0.1
  End
""")

            #graduates line widths or point sizes

            if themetype == "graduated_lines":
                grass.run_command('d.vect',
                                  map=map,
                                  type=type,
                                  layer=layer,
                                  where=sqlwhere,
                                  color=linecolor,
                                  fcolor=themecolor,
                                  icon=icon,
                                  size=ptsize,
                                  width=ptsize)

            else:
                grass.run_command('d.vect',
                                  map=map,
                                  type=type,
                                  layer=layer,
                                  where=sqlwhere,
                                  color=linecolor,
                                  fcolor=themecolor,
                                  icon=icon,
                                  size=ptsize)

                out(
                    f_psmap, locals(), """\
vpoints $map
  type $type
  layer $layer
  where $sqlwhere
  color $linecolor
  fcolor $themecolor
  symbol $icon
  size $ptsize
  label $rangemin - $rangemax
end
""")

            ptsize -= pointstep

            line1 -= lineht
            line2 -= lineht
            i -= 1

    # Create graphic legend
    f_graph.close()
    if flag_l:
        grass.run_command('d.erase')
        grass.run_command('d.graph', input=tmp_graph)

    # Create group file for GIS Manager
    f_group.write("End\n")
    f_group.close()
    if flag_g:
        shutil.copyfile(tmp_group, "%s.dm" % group)

    # Create ps.map map file
    f_psmap.write("end\n")
    f_psmap.close()
    if psmap:
        shutil.copyfile(tmp_psmap, "%s.psmap" % psmap)

    # Create ps.map legend file
    f_psleg.write("end\n")
    f_psleg.close()
    if psmap:
        shutil.copyfile(tmp_psleg, "%s_legend.psmap" % psmap)

    # Create text file to use with d.graph in GIS Manager
    f_gisleg.close()
    if flag_s:
        tmpdir = os.path.dirname(tmp_gisleg)
        tlegfile = os.path.join(tmpdir, "gismlegend.txt")
        shutil.copyfile(tmp_gisleg, tlegfile)
Ejemplo n.º 37
0
def main():
    mapname = options["map"]
    layer = options["layer"]
    option = options["option"]
    units = options["units"]
    sort = options["sort"]
    fs = separator(options["separator"])

    nuldev = open(os.devnull, "w")

    if not grass.find_file(mapname, "vector")["file"]:
        grass.fatal(_("Vector map <%s> not found") % mapname)

    if int(layer) in grass.vector_db(mapname):
        colnames = grass.vector_columns(mapname,
                                        layer,
                                        getDict=False,
                                        stderr=nuldev)
        isConnection = True
    else:
        isConnection = False
        colnames = ["cat"]

    if option == "coor":
        extracolnames = ["x", "y", "z"]
    else:
        extracolnames = [option]

    if units == "percent":
        unitsp = "meters"
    elif units:
        unitsp = units
    else:
        unitsp = None

    # NOTE: we suppress -1 cat and 0 cat
    if isConnection:
        f = grass.vector_db(map=mapname)[int(layer)]
        p = grass.pipe_command("v.db.select",
                               flags="e",
                               quiet=True,
                               map=mapname,
                               layer=layer)
        records1 = []
        catcol = -1
        ncols = 0
        for line in p.stdout:
            cols = decode(line).rstrip("\r\n").split("|")
            if catcol == -1:
                ncols = len(cols)
                for i in range(0, ncols):
                    if cols[i] == f["key"]:
                        catcol = i
                        break
                if catcol == -1:
                    grass.fatal(
                        _("There is a table connected to input vector map '%s', but "
                          "there is no key column '%s'.") %
                        (mapname, f["key"]))
                continue
            if cols[catcol] == "-1" or cols[catcol] == "0":
                continue
            records1.append(cols[:catcol] + [int(cols[catcol])] +
                            cols[(catcol + 1):])
        p.wait()
        if p.returncode != 0:
            sys.exit(1)

        records1.sort(key=lambda r: r[catcol])

        if len(records1) == 0:
            try:
                grass.fatal(
                    _("There is a table connected to input vector map '%s', but "
                      "there are no categories present in the key column '%s'. Consider using "
                      "v.to.db to correct this.") % (mapname, f["key"]))
            except KeyError:
                pass

        # fetch the requested attribute sorted by cat:
        p = grass.pipe_command(
            "v.to.db",
            flags="p",
            quiet=True,
            map=mapname,
            option=option,
            layer=layer,
            units=unitsp,
        )
        records2 = []
        for line in p.stdout:
            fields = decode(line).rstrip("\r\n").split("|")
            if fields[0] in ["cat", "-1", "0"]:
                continue
            records2.append([int(fields[0])] + fields[1:])
        p.wait()
        records2.sort()

        # make pre-table
        # len(records1) may not be the same as len(records2) because
        # v.db.select can return attributes that are not linked to features.
        records3 = []
        for r2 in records2:
            rec = list(filter(lambda r1: r1[catcol] == r2[0], records1))
            if len(rec) > 0:
                res = rec[0] + r2[1:]
            elif flags["d"]:
                res = [r2[0]] + [""] * (ncols - 1) + r2[1:]
            else:
                continue
            records3.append(res)
    else:
        catcol = 0
        records1 = []
        p = grass.pipe_command("v.category",
                               inp=mapname,
                               layer=layer,
                               option="print")
        for line in p.stdout:
            field = int(decode(line).rstrip())
            if field > 0:
                records1.append(field)
        p.wait()
        records1.sort()
        records1 = uniq(records1)

        # make pre-table
        p = grass.pipe_command(
            "v.to.db",
            flags="p",
            quiet=True,
            map=mapname,
            option=option,
            layer=layer,
            units=unitsp,
        )
        records3 = []
        for line in p.stdout:
            fields = decode(line).rstrip("\r\n").split("|")
            if fields[0] in ["cat", "-1", "0"]:
                continue
            records3.append([int(fields[0])] + fields[1:])
        p.wait()
        records3.sort()

    # print table header
    if not flags["c"]:
        sys.stdout.write(fs.join(colnames + extracolnames) + "\n")

    # make and print the table:
    numcols = len(colnames) + len(extracolnames)

    # calculate percents if requested
    if units == "percent" and option != "coor":
        # calculate total value
        total = 0
        for r in records3:
            total += float(r[-1])

        # calculate percentages
        records4 = [float(r[-1]) * 100 / total for r in records3]
        if type(records1[0]) == int:
            records3 = [[r1] + [r4] for r1, r4 in zip(records1, records4)]
        else:
            records3 = [r1 + [r4] for r1, r4 in zip(records1, records4)]

    # sort results
    if sort:
        if sort == "asc":
            if option == "coor":
                records3.sort(
                    key=lambda r: (float(r[-3]), float(r[-2]), float(r[-1])))
            else:
                records3.sort(key=lambda r: float(r[-1]))
        else:
            if option == "coor":
                records3.sort(
                    key=lambda r: (float(r[-3]), float(r[-2]), float(r[-1])),
                    reverse=True,
                )
            else:
                records3.sort(key=lambda r: float(r[-1]), reverse=True)

    for r in records3:
        sys.stdout.write(fs.join(map(str, r)) + "\n")
def main():
    global TMP_MAPS, vector, Land_cover, morpho_zones, distance_to, tile_size, id, population, area, built_up, output, png, nsres, ewres, lc_classes_list, morpho_classes_list
    TMP_MAPS = []
    # user's values
    vector = options['vector']
    Land_cover = options['land_cover']
    morpho_zones = options['morpho_zones'] if options['morpho_zones'] else ""
    distance_to = options['distance_to'] if options['distance_to'] else ""
    tile_size = options['tile_size']
    id = options['id']
    population = options['population']
    area = options['area']
    built_up = options['built_up_category'] if options[
        'built_up_category'] else ""
    output = options['output']
    png = options['png']
    lc_list = options['lc_list'].split(",") if options['lc_list'] else ""
    morpho_list = options['morpho_list'].split(
        ",") if options['morpho_list'] else ""
    # vector exists?
    result = gscript.find_file(vector, element='vector')
    if len(result['name']) == 0:
        gscript.fatal(_("Input vector <%s> not found") % vector)

    # Land_cover exists?
    result = gscript.find_file(Land_cover, element='cell')
    if len(result['name']) == 0:
        gscript.fatal(_("Input Land Cover <%s> not found") % Land_cover)

    # id column exists ?
    if id not in gscript.vector_columns(vector).keys():
        gscript.fatal(
            _("<%s> column does not exist for vector %s") % (id, vector))

# is  id column numeric?
    coltype = gscript.vector_columns(vector)[id]['type']

    if coltype not in ('INTEGER'):
        gscript.fatal(_("<%s> column must be Integer") % (id))

    # population column exists ?
    if population not in gscript.vector_columns(vector).keys():
        gscript.fatal(
            _("<%s> column does not exist for vector %s") %
            (population, vector))

    # is  population column numeric?
    coltype = gscript.vector_columns(vector)[population]['type']

    if coltype not in ('INTEGER', 'DOUBLE PRECISION'):
        gscript.fatal(_("<%s> column must be numeric") % (population))

    # area column exists ?
    if area not in gscript.vector_columns(vector).keys():
        gscript.fatal(
            _("<%s> column does not exist for vector %s") % (area, vector))

    # is  area column numeric?
    coltype = gscript.vector_columns(vector)[area]['type']
    if coltype not in ('INTEGER', 'DOUBLE PRECISION'):
        gscript.fatal(_("<%s> column must be numeric") % (area))

    # is tile_size diffrent from null?
    if (int(tile_size) == 0):
        gscript.fatal(_("Tile size can't be NULL"))

    # morpho_zones exists?
    if (morpho_zones != ''):
        result = gscript.find_file(morpho_zones, element='cell')
        if (len(result['name']) == 0):
            gscript.fatal(
                _("Input morpho zones <%s> not found") % morpho_zones)

    # distance_to exists?
    if (distance_to != ''):
        result = gscript.find_file(distance_to, element='cell')
        if (len(result['name']) == 0):
            gscript.fatal(_("Input distance_to <%s> not found") % distance_to)

    # data preparation : extract classes and resolution from the Land Cover
    Data = Data_prep(Land_cover)
    nsres = Data[0]  ## north-south resolution
    ewres = Data[1]  ## east-west resolution
    if (lc_list == ""):
        lc_classes_list = Data[2]
    else:
        lc_classes_list = lc_list

    print(lc_classes_list)

    ## creating a gridded vector: each grid has a size of "tile_size"
    gscript.run_command('g.region', raster=Land_cover, res=tile_size)
    gscript.mapcalc("empty_grid=rand(0 ,999999999 )",
                    overwrite=True,
                    seed='auto')  #creating a raster with random values
    gscript.run_command('r.clump',
                        input='empty_grid',
                        output='empty_grid_Clump',
                        overwrite=True)  #assigning a unique value to each grid
    gscript.run_command('r.to.vect',
                        input='empty_grid_Clump',
                        output='grid_vector',
                        type='area',
                        overwrite=True)  #raster to vector

    admin_boundaries(vector.split("@")[0], id)
    ## calculating classes' proportions within each grid
    proportion_class_grid(Land_cover, 'grid_vector', lc_classes_list, "")
    ## calculating classes' proportions within each administrative unit
    proportion_class_admin(vector.split("@")[0], lc_classes_list, "")

    if (morpho_zones == ''):
        if (distance_to != ''):
            gscript.run_command('v.what.rast',
                                map='grid_vector',
                                type='centroid',
                                raster=distance_to,
                                column='distance')
            gscript.run_command('v.rast.stats',
                                map=vector.split("@")[0] + '_rastTovect',
                                raster=distance_to,
                                column_prefix='distance',
                                method='average',
                                flags='c')

    else:
        if (distance_to != ''):
            gscript.run_command('v.what.rast',
                                map='grid_vector',
                                type='centroid',
                                raster=distance_to,
                                column='distance')
            gscript.run_command('v.rast.stats',
                                map=vector.split("@")[0] + '_rastTovect',
                                raster=distance_to,
                                column_prefix='distance',
                                method='average',
                                flags='c')
        #Extract morpho layer's classes
        if (morpho_list == ""):
            morpho_classes_list = Data_prep(morpho_zones.split("@")[0])[2]
        else:
            morpho_classes_list = morpho_list
        #print(morpho_classes_list)

        # calculating classes' proportions within each grid
        proportion_class_grid(
            morpho_zones.split("@")[0], 'grid_vector', morpho_classes_list,
            "_morpho")

        # calculating classes' proportions within each administrative unit
        proportion_class_admin(
            vector.split("@")[0], morpho_classes_list, "_morpho")

    #RF
    RandomForest(vector.split("@")[0], id)
Ejemplo n.º 39
0
def main():
    mapname = options['map']
    option = options['option']
    layer = options['layer']
    units = options['units']

    nuldev = open(os.devnull, 'w')

    if not grass.find_file(mapname, 'vector')['file']:
        grass.fatal(_("Vector map <%s> not found") % mapname)

    if int(layer) in grass.vector_db(mapname):
        colnames = grass.vector_columns(mapname,
                                        layer,
                                        getDict=False,
                                        stderr=nuldev)
        isConnection = True
    else:
        isConnection = False
        colnames = ['cat']

    if option == 'coor':
        extracolnames = ['x', 'y', 'z']
    else:
        extracolnames = [option]

    if units == 'percent':
        unitsp = 'meters'
    elif units:
        unitsp = units
    else:
        unitsp = None

    # NOTE: we suppress -1 cat and 0 cat
    if isConnection:
        f = grass.vector_db(map=mapname)[int(layer)]
        p = grass.pipe_command('v.db.select',
                               quiet=True,
                               map=mapname,
                               layer=layer)
        records1 = []
        catcol = -1
        ncols = 0
        for line in p.stdout:
            cols = decode(line).rstrip('\r\n').split('|')
            if catcol == -1:
                ncols = len(cols)
                for i in range(0, ncols):
                    if cols[i] == f['key']:
                        catcol = i
                        break
                if catcol == -1:
                    grass.fatal(
                        _("There is a table connected to input vector map '%s', but "
                          "there is no key column '%s'.") %
                        (mapname, f['key']))
                continue
            if cols[catcol] == '-1' or cols[catcol] == '0':
                continue
            records1.append(cols[:catcol] + [int(cols[catcol])] +
                            cols[(catcol + 1):])
        p.wait()
        if p.returncode != 0:
            sys.exit(1)

        records1.sort(key=lambda r: r[catcol])

        if len(records1) == 0:
            try:
                grass.fatal(
                    _("There is a table connected to input vector map '%s', but "
                      "there are no categories present in the key column '%s'. Consider using "
                      "v.to.db to correct this.") % (mapname, f['key']))
            except KeyError:
                pass

        # fetch the requested attribute sorted by cat:
        p = grass.pipe_command('v.to.db',
                               flags='p',
                               quiet=True,
                               map=mapname,
                               option=option,
                               layer=layer,
                               units=unitsp)
        records2 = []
        for line in p.stdout:
            fields = decode(line).rstrip('\r\n').split('|')
            if fields[0] in ['cat', '-1', '0']:
                continue
            records2.append([int(fields[0])] + fields[1:])
        p.wait()
        records2.sort()

        # make pre-table
        # len(records1) may not be the same as len(records2) because
        # v.db.select can return attributes that are not linked to features.
        records3 = []
        for r2 in records2:
            rec = list(filter(lambda r1: r1[catcol] == r2[0], records1))
            if len(rec) > 0:
                res = rec[0] + r2[1:]
            elif flags['d']:
                res = [r2[0]] + [''] * (ncols - 1) + r2[1:]
            else:
                continue
            records3.append(res)
    else:
        catcol = 0
        records1 = []
        p = grass.pipe_command('v.category',
                               inp=mapname,
                               layer=layer,
                               option='print')
        for line in p.stdout:
            field = int(decode(line).rstrip())
            if field > 0:
                records1.append(field)
        p.wait()
        records1.sort()
        records1 = uniq(records1)

        # make pre-table
        p = grass.pipe_command('v.to.db',
                               flags='p',
                               quiet=True,
                               map=mapname,
                               option=option,
                               layer=layer,
                               units=unitsp)
        records3 = []
        for line in p.stdout:
            fields = decode(line).rstrip('\r\n').split('|')
            if fields[0] in ['cat', '-1', '0']:
                continue
            records3.append([int(fields[0])] + fields[1:])
        p.wait()
        records3.sort()

    # print table header
    if not flags['c']:
        sys.stdout.write('|'.join(colnames + extracolnames) + '\n')

    # make and print the table:
    numcols = len(colnames) + len(extracolnames)

    # calculate percents if requested
    if units == 'percent' and option != 'coor':
        # calculate total value
        total = 0
        for r in records3:
            total += float(r[-1])

        # calculate percentages
        records4 = [float(r[-1]) * 100 / total for r in records3]
        if type(records1[0]) == int:
            records3 = [[r1] + [r4] for r1, r4 in zip(records1, records4)]
        else:
            records3 = [r1 + [r4] for r1, r4 in zip(records1, records4)]

    # sort results
    if options['sort']:
        if options['sort'] == 'asc':
            if options['option'] == 'coor':
                records3.sort(
                    key=lambda r: (float(r[-3]), float(r[-2]), float(r[-1])))
            else:
                records3.sort(key=lambda r: float(r[-1]))
        else:
            if options['option'] == 'coor':
                records3.sort(key=lambda r:
                              (float(r[-3]), float(r[-2]), float(r[-1])),
                              reverse=True)
            else:
                records3.sort(key=lambda r: float(r[-1]), reverse=True)

    for r in records3:
        sys.stdout.write('|'.join(map(str, r)) + '\n')
Ejemplo n.º 40
0
def main():
    map = options['map']
    layer = options['layer']
    columns = options['columns'].split(',')

    mapset = grass.gisenv()['MAPSET']

    # does map exist in CURRENT mapset?
    if not grass.find_file(map, element='vector', mapset=mapset)['file']:
        grass.fatal(_("Vector map <%s> not found in current mapset") % map)

    f = grass.vector_layer_db(map, layer)

    table = f['table']
    keycol = f['key']
    database = f['database']
    driver = f['driver']

    if not table:
        grass.fatal(_("There is no table connected to the input vector map. "
                      "Unable to delete any column. Exiting."))

    if keycol in columns:
        grass.fatal(_("Unable to delete <%s> column as it is needed to keep table <%s> "
                      "connected to the input vector map <%s>") %
                    (keycol, table, map))

    for column in columns:
        if column not in grass.vector_columns(map, layer):
            grass.warning(_("Column <%s> not found in table <%s>. Skipped") % (column, table))
            continue

        if driver == "sqlite":
            # echo "Using special trick for SQLite"
            # http://www.sqlite.org/faq.html#q11
            colnames = []
            coltypes = []
            for f in grass.db_describe(table, database=database, driver=driver)['cols']:
                if f[0] == column:
                    continue
                colnames.append(f[0])
                coltypes.append("%s %s" % (f[0], f[1]))

            colnames = ", ".join(colnames)
            coltypes = ", ".join(coltypes)

            cmds = [
                "BEGIN TRANSACTION",
                "CREATE TEMPORARY TABLE ${table}_backup(${coldef})",
                "INSERT INTO ${table}_backup SELECT ${colnames} FROM ${table}",
                "DROP TABLE ${table}",
                "CREATE TABLE ${table}(${coldef})",
                "INSERT INTO ${table} SELECT ${colnames} FROM ${table}_backup",
                "CREATE UNIQUE INDEX ${table}_cat ON ${table} (${keycol} )",
                "DROP TABLE ${table}_backup",
                "COMMIT"
            ]
            tmpl = string.Template(';\n'.join(cmds))
            sql = tmpl.substitute(table=table, coldef=coltypes, colnames=colnames, keycol=keycol)
        else:
            sql = "ALTER TABLE %s DROP COLUMN %s" % (table, column)

        try:
            grass.write_command('db.execute', input='-', database=database, driver=driver,
                                stdin=sql)
        except CalledModuleError:
            grass.fatal(_("Deleting column failed"))

    # write cmd history:
    grass.vector_history(map)
Ejemplo n.º 41
0
def main():
    color  = options['color']
    column = options['column']
    layer  = options['layer']
    map    = options['map']
    range  = options['range']
    raster = options['raster']
    rgb_column = options['rgb_column']
    rules  = options['rules']
    flip   = flags['n']
    
    global tmp, tmp_colr, tmp_vcol
    pid = os.getpid()
    tmp = tmp_colr = tmp_vcol = None
    
    mapset = grass.gisenv()['MAPSET']
    gisbase = os.getenv('GISBASE')
    
    # does map exist in CURRENT mapset?
    kv = grass.find_file(map, element = 'vector', mapset = mapset)
    if not kv['file']:
        grass.fatal(_("Vector map <%s> not found in current mapset") % map)
    
    vector = map.split('@', 1)
    
    # sanity check mutually exclusive color options
    if not options['color'] and not options['raster'] and not options['rules']:
        grass.fatal(_("Pick one of color, rules, or raster options"))
    
    if color:
        #### check the color rule is valid
        color_opts = os.listdir(os.path.join(gisbase, 'etc', 'colors'))
        color_opts += ['random', 'grey.eq', 'grey.log', 'rules']
        if color not in color_opts:
            grass.fatal(_("Invalid color rule <%s>\n") % color +
                        _("Valid options are: %s") % ' '.join(color_opts))
    elif raster:
        if not grass.find_file(raster)['name']:
            grass.fatal(_("Raster raster map <%s> not found") % raster)
    elif rules:
        if not os.access(rules, os.R_OK):
            grass.fatal(_("Unable to read color rules file <%s>") % rules)
    
    # column checks
    # check input data column
    cols = grass.vector_columns(map, layer = layer)
    if column not in cols:
        grass.fatal(_("Column <%s> not found") % column)
    ncolumn_type = cols[column]['type']
    if ncolumn_type not in ["INTEGER", "DOUBLE PRECISION"]:
        grass.fatal(_("Column <%s> is not numeric but %s") % (column, ncolumn_type))
    
    # check if GRASSRGB column exists, make it if it doesn't
    table = grass.vector_db(map)[int(layer)]['table']
    if rgb_column not in cols:
        # RGB Column not found, create it
        grass.message(_("Creating column <%s>...") % rgb_column)
        try:
            grass.run_command('v.db.addcolumn', map = map, layer = layer, column = "%s varchar(11)" % rgb_column)
        except CalledModuleError:
            grass.fatal(_("Creating color column"))
    else:
        column_type = cols[rgb_column]['type']
        if column_type not in ["CHARACTER", "TEXT"]:
            grass.fatal(_("Column <%s> is not of compatible type (found %s)") % (rgb_column, column_type))
        else:
            num_chars = dict([(v[0], int(v[2])) for v in grass.db_describe(table)['cols']])[rgb_column]
            if num_chars < 11:
                grass.fatal(_("Color column <%s> is not wide enough (needs 11 characters)"), rgb_column)
    
    cvals = grass.vector_db_select(map, layer = int(layer), columns = column)['values'].values()
    
    # find data range
    if range:
        # order doesn't matter
        vals = range.split(',')
    else:
        grass.message(_("Scanning values..."))
        vals = [float(x[0]) for x in cvals]
    
    minval = min(vals)
    maxval = max(vals)

    grass.verbose(_("Range: [%s, %s]") % (minval, maxval))
    if minval is None or maxval is None:
        grass.fatal(_("Scanning data range"))

    # setup internal region
    grass.use_temp_region()
    grass.run_command('g.region', rows = 2, cols = 2)
    
    tmp_colr = "tmp_colr_%d" % pid
    
    # create dummy raster map
    if ncolumn_type == "INTEGER":
        grass.mapcalc("$tmp_colr = int(if(row() == 1, $minval, $maxval))",
                      tmp_colr = tmp_colr, minval = minval, maxval = maxval)
    else:
        grass.mapcalc("$tmp_colr = double(if(row() == 1, $minval, $maxval))",
                      tmp_colr = tmp_colr, minval = minval, maxval = maxval)
    
    if color:
        color_cmd = {'color': color}
    elif raster:
        color_cmd = {'raster': raster}
    elif rules:
        color_cmd = {'rules': rules}
    
    if flip:
        flip_flag = 'n'
    else:
        flip_flag = ''
    
    grass.run_command('r.colors', map = tmp_colr, flags = flip_flag, quiet = True, **color_cmd)
    
    tmp = grass.tempfile()
    
    # calculate colors and write SQL command file
    grass.message(_("Looking up colors..."))
    
    f = open(tmp, 'w')
    p = grass.feed_command('r.what.color', flags = 'i', input = tmp_colr, stdout = f)
    lastval = None
    for v in sorted(vals):
        if v == lastval:
            continue
        p.stdin.write('%f\n' % v)
    p.stdin.close()
    p.wait()
    f.close()
    
    tmp_vcol = "%s_vcol.sql" % tmp
    fi = open(tmp, 'r')
    fo = open(tmp_vcol, 'w')
    t = string.Template("UPDATE $table SET $rgb_column = '$colr' WHERE $column = $value;\n")
    found = 0
    for line in fi:
        [value, colr] = line.split(': ')
        colr = colr.strip()
        if len(colr.split(':')) != 3:
            continue
        fo.write(t.substitute(table = table, rgb_column = rgb_column, colr = colr, column = column, value = value))
        found += 1
    fi.close()
    fo.close()
    
    if not found:
        grass.fatal(_("No values found in color range"))
    
    # apply SQL commands to update the table with values
    grass.message(_("Writing %s colors...") % found)
    
    try:
        grass.run_command('db.execute', input = tmp_vcol)
    except CalledModuleError:
        grass.fatal(_("Processing SQL transaction"))
    
    if flags['s']:
        vcolors = "vcolors_%d" % pid
        grass.run_command('g.rename', raster = (tmp_colr, vcolors), quiet = True)
        grass.message(_("Raster map containing color rules saved to <%s>") % vcolors)
        # TODO save full v.colors command line history
        grass.run_command('r.support', map = vcolors,
                          history = "",
                          source1 = "vector map = %s" % map,
                          source2 = "column = %s" % column,
                          title = _("Dummy raster to use as thematic vector legend"),
                          description = "generated by v.colors using r.mapcalc")
        grass.run_command('r.support', map = vcolors,
                          history = _("RGB saved into <%s> using <%s%s%s>") % (rgb_column, color, raster, rules))
Ejemplo n.º 42
0
def main():
    global tmp_graph, tmp_group, tmp_psmap, tmp_psleg, tmp_gisleg

    breakpoints = options['breakpoints']
    colorscheme = options['colorscheme']
    column = options['column']
    endcolor = options['endcolor']
    group = options['group']
    layer = options['layer']
    linecolor = options['linecolor']
    map = options['map']
    maxsize = options['maxsize']
    monitor = options['monitor']
    nint = options['nint']
    pointcolor = options['pointcolor']
    psmap = options['psmap']
    size = options['size']
    startcolor = options['startcolor']
    themecalc = options['themecalc']
    themetype = options['themetype']
    type = options['type']
    where = options['where']
    icon = options['icon']

    flag_f = flags['f']
    flag_g = flags['g']
    flag_l = flags['l']
    flag_m = flags['m']
    flag_s = flags['s']
    flag_u = flags['u']

    layer = int(layer)
    nint = int(nint)
    size = float(size)
    maxsize = float(maxsize)

    # check column type
    inf = grass.vector_columns(map, layer)
    if column not in inf:
	grass.fatal(_("No such column <%s>") % column)
    coltype = inf[column]['type'].lower()

    if coltype not in ["integer", "double precision"]:
	grass.fatal(_("Column <%s> is of type <%s> which is not numeric.") % (column, coltype))

    # create temporary file to hold d.graph commands for legend
    tmp_graph = grass.tempfile()
    # Create temporary file to commands for GIS Manager group
    tmp_group = grass.tempfile()
    # Create temporary file for commands for ps.map map file
    tmp_psmap = grass.tempfile()
    # Create temporary file for commands for ps.map legend file
    tmp_psleg = grass.tempfile()
    # create file to hold elements for GIS Manager legend
    tmp_gisleg = grass.tempfile()

    # Set display variables for group
    atype = int(type == "area")
    ptype = int(type == "point")
    ctype = int(type == "centroid")
    ltype = int(type == "line")
    btype = int(type == "boundary")

    # if running in the GUI, do not create a graphic legend in an xmon
    if flag_s:
        flag_l = False
        # if running in GUI, turn off immediate mode rendering so that the
        # iterated d.vect commands will composite using the display driver
        os.environ['GRASS_PNG_READ'] = 'TRUE'
        os.environ['GRASS_PNG_AUTO_WRITE'] = 'FALSE'

    db = grass.vector_db(map)[1]
    if not db or not db['table']:
        grass.fatal(_("No table connected or layer <%s> does not exist.") % layer)
    table = db['table']
    database = db['database']
    driver = db['driver']

    # update color values to the table?
    if flag_u:
        # test, if the column GRASSRGB is in the table
        s = grass.read_command('db.columns', table = table, database = database, driver = driver)
        if 'grassrgb' not in s.splitlines():
            msg(locals(), _("Creating column 'grassrgb' in table <$table>"))
            sql = "ALTER TABLE %s ADD COLUMN grassrgb varchar(11)" % table
            grass.write_command('db.execute', database = database, driver = driver, stdin = sql)

    # Group name
    if not group:
        group = "themes"

    f_group = file(tmp_group, 'w')
    f_group.write("Group %s\n" % group)

    # Calculate statistics for thematic intervals
    if type == "line":
        stype = "line"
    else:
        stype = ["point", "centroid"]

    if not where:
        where = None

    stats = grass.read_command('v.univar', flags = 'eg', map = map, type = stype, column = column, where = where, layer = layer)
    stats = grass.parse_key_val(stats)

    min  = float(stats['min'])
    max  = float(stats['max'])
    mean = float(stats['mean'])
    sd   = float(stats['population_stddev'])
    q1   = float(stats['first_quartile'])
    q2   = float(stats['median'])
    q3   = float(stats['third_quartile'])
    q4   = max

    ptsize = size

    if breakpoints and themecalc != "custom_breaks":
        grass.warning(_("Custom breakpoints ignored due to themecalc setting."))

    # set interval for each thematic map calculation type
    if themecalc == "interval":
        numint = nint
        step = float(max - min) / numint
        breakpoints = [min + i * step for i in xrange(numint + 1)]
        annotations = ""
    elif themecalc == "std_deviation":
        # 2 standard deviation units on either side of mean,
        # plus min to -2 sd units and +2 sd units to max, if applicable
        breakpoints = [min] + [i for i in [(mean + i * sd) for i in [-2,-1,0,1,2]] if min < i < max] + [max]
        annotations = [""] + [("%dsd" % i) for (i, j) in [(i, mean + i * sd) for i in [-2,-1,0,1,2]] if (min < j < max)] + [""]
        annotations = ";".join(annotations)
        numint = len(breakpoints) - 1
    elif themecalc == "quartiles":
        numint=4
        # one for each quartile
        breakpoints = [min, q1, q2, q3, max]
        annotations = " %f; %f; %f; %f" % (q1, q2, q3, q4)
    elif themecalc == "custom_breaks":
        if not breakpoints:
            breakpoints = sys.stdin.read()
        breakpoints = [int(x) for x in breakpoints.split()]
        numint = len(breakpoints) - 1
        annotations = ""
    else:
        grass.fatal(_("Unknown themecalc type <%s>") % themecalc)

    pointstep = (maxsize - ptsize) / (numint - 1)

    # Prepare legend cuts for too large numint
    if numint > max_leg_items:
        xupper = int(numint - max_leg_items / 2) + 1
        xlower = int(max_leg_items / 2) + 1
    else:
        xupper = 0
        xlower = 0

    # legend title
    f_graph = file(tmp_graph, 'w')
    out(f_graph, locals(), """\
color 0:0:0
size 2 2
move 1 95
text Thematic map legend for column $column of map $map
size 1.5 1.8
move 4 90
text Value range: $min - $max
""")

    f_gisleg = file(tmp_gisleg, 'w')
    out(f_gisleg, locals(), """\
title - - - {Thematic map legend for column $column of map $map}
""")

    f_psleg = file(tmp_psleg, 'w')
    out(f_psleg, locals(), """\
text 1% 95% Thematic map legend for column $column of map $map
  ref bottom left
end
text 4% 90% Value range: $min - $max
  ref bottom left
end
""")

    msg(locals(), _("Thematic map legend for column $column of map $map"))
    msg(locals(), _("Value range: $min - $max"))

    colorschemes = {
        "blue-red":		("0:0:255",	"255:0:0"),
        "red-blue":		("255:0:0",	"0:0:255"),
        "green-red":	("0:255:0",	"255:0:0"),
        "red-green":	("255:0:0",	"0:255:0"),
        "blue-green":	("0:0:255",	"0:255:0"),
        "green-blue":	("0:255:0",	"0:0:255"),
        "cyan-yellow":	("0:255:255",	"255:255:0"),
        "yellow-cyan":	("255:255:0",	"0:255:255"),
        "custom_gradient":	(startcolor,	endcolor)
        }

    # open file for psmap instructions
    f_psmap = file(tmp_psmap, 'w')

    # graduated color thematic mapping
    if themetype == "graduated_colors":
        if colorscheme in colorschemes:
            startc, endc = colorschemes[colorscheme]
        # set color schemes for graduated color maps
        elif colorscheme == "single_color":
            if themetype == "graduated_points":
                startc = endc = linecolor
            else:
                startc = endc = pointcolor
        else:
            grass.fatal(_("This should not happen: parser error. Unknown color scheme %s") % colorscheme)

        color = __builtins__.map(int, startc.split(":"))
        endcolor = __builtins__.map(int, endc.split(":"))

        #The number of color steps is one less then the number of classes
        nclrstep = numint - 1
        clrstep = [(a - b) / nclrstep for a, b in zip(color, endcolor)]

        themecolor = startc

        # display graduated color themes
        if themecalc == "interval":
            out(f_graph, locals(), """\
move 4 87
text Mapped by $numint intervals of $step
""")

            out(f_gisleg, locals(), """\
subtitle - - - {Mapped by $numint intervals of $step}
""")

            out(f_psleg, locals(), """\
text 4% 87% Mapped by $numint intervals of $step
  ref bottom left
end
""")

            msg(locals(), _("Mapped by $numint intervals of $step"))

        # display graduated color themes for standard deviation units
        if themecalc == "std_deviation":
            out(f_graph, locals(), """\
move 4 87
text Mapped by standard deviation units of $sd (mean = $mean)
""")

            out(f_gisleg, locals(), """\
subtitle - - - {Mapped by standard deviation units of $sd (mean = $mean)}
""")

            out(f_psleg, locals(), """\
text 4% 87% Mapped by standard deviation units of $sd (mean = $mean)
  ref bottom left
end
""")

            msg(locals(), _("Mapped by standard deviation units of $sd (mean = $mean)"))

        # display graduated color themes for quartiles
        if themecalc == "quartiles":
            out(f_graph, locals(), """\
move 4 87
text Mapped by quartiles (median = $q2)
""")

            out(f_gisleg, locals(), """\
subtitle - - - {Mapped by quartiles (median = $q2)}
""")

            out(f_psleg, locals(), """\
text 4% 87% Mapped by quartiles (median = $q2)
  ref bottom left
end
""")

            msg(locals(), _("Mapped by quartiles (median = $q2)"))

        f_graph.write("""\
move 4 83
text Color
move 14 83
text Value
move 4 80
text =====
move 14 80
text ============
""")

        f_psleg.write("""\
text 4% 83% Color
  ref bottom left
end
text 14% 83% Value
  ref bottom left
end
text 4% 80% =====
  ref bottom left
end
text 14% 80% ============
  ref bottom left
end
""")

        sys.stdout.write("Color(R:G:B)\tValue\n")
        sys.stdout.write("============\t==========\n")

        line1 = 78
        line2 = 76
        line3 = 75

        i = 1
        first = True

        while i < numint:
            if flag_m:
                # math notation
                if first:
                    closebracket = "]"
                    openbracket = "["
                    mincomparison = ">="
                    first = False
                else:
                    closebracket = "]"
                    openbracket = "]"
                    mincomparison = ">"
            else:
                closebracket = "" 
                openbracket = ""
                if first:
                    mincomparison = ">="
                    first = False
                else:
                    mincomparison = ">"

            themecolor = ":".join(__builtins__.map(str,color))
            if flag_f:
                linecolor = "none"
            else:
                if type in ["line", "boundary"]:
                    linecolor = themecolor
                else:
                    linecolor = linecolor

            rangemin = __builtins__.min(breakpoints)
            rangemax = __builtins__.max(breakpoints)

            if not annotations:
                extranote = ""
            else:
                extranote = annotations[i]

            if i < xlower or i >= xupper:
                xline1 = line2 + 2
                xline3 = line2 - 1
                out(f_graph, locals(), """\
color $themecolor
polygon
5 $xline1
8 $xline1
8 $xline3
5 $xline3
color $linecolor
move 5 $xline1
draw 8 $xline1
draw 8 $xline3
draw 5 $xline3
draw 5 $xline1
move 14 $line2
color 0:0:0
text $openbracket$rangemin - $rangemax$closebracket $extranote
""")
            else:
                if i == xlower:
                    out(f_graph, locals(), """\
color 0:0:0
move 10 $line2
text ...
""")
                else:
                    #undo next increment
                    line2 += 4

            if i < xlower or i >= xupper:
                out(f_gisleg, locals(), """\
area $themecolor $linecolor - {$openbracket$rangemin - $rangemax$closebracket $extranote}
""")

                if type in ["line", "boundary"]:
                    out(f_psleg, locals(), """\
line 5% $xline1% 8% $xline1%
  color $linecolor
end
text 14% $xline1% $openbracket$rangemin - $rangemax$closebracket $extranote
  ref center left
end
""")
                elif type in ["point", "centroid"]:
                    out(f_psleg, locals(), """\
point 8% $xline1%
  color $linecolor
  fcolor $themecolor
  size $size
  symbol $icon
end
text 14% $xline1% $openbracket$rangemin - $rangemax$closebracket $extranote
  ref center left
end
""")
                else:
                    out(f_psleg, locals(), """\
rectangle 5% $xline1% 8% $xline3%
  color 0:0:0
  fcolor $themecolor
end
text 14% $xline3% $openbracket$rangemin - $rangemax$closebracket DCADCA $extranote
  ref bottom left
end
""")
            else:
                if i == xlower:
                    out(f_psleg, locals(), """\
color 0:0:0
text 14% $xline3% ...
  ref bottom left
end
""")

                f_gisleg.write("text - - - {...}\n")

            sys.stdout.write(subs(locals(), "$themecolor\t\t$openbracket$rangemin - $rangemax$closebracket $extranote\n"))
            if not where:
                sqlwhere = subs(locals(), "$column $mincomparison $rangemin AND $column <= $rangemax")
            else:
                sqlwhere = subs(locals(), "$column $mincomparison $rangemin AND $column <= $rangemax AND $where")

            # update color to database?
            if flag_u:
                sql = subs(locals(), "UPDATE $table SET GRASSRGB = '$themecolor' WHERE $sqlwhere")
                grass.write_command('db.execute', database = database, driver = driver, stdin = sql)

            # Create group for GIS Manager
            if flag_g:
                # change rgb colors to hex
                xthemecolor = "#%02X%02X%02X" % tuple(__builtins__.map(int, themecolor.split(":")))
                #xlinecolor=`echo $linecolor | awk -F: '{printf("#%02X%02X%02X\n",$1,$2,$3)}'`

                if "$linecolor" == "black":
                    xlinecolor = "#000000"
                else:
                    xlinecolor = xthemecolor


                # create group entry
                out(f_group, locals(), """\
  _check 1
  Vector $column = $rangemin - $rangemax
    _check 1
    map $map
    display_shape 1
    display_cat 0
    display_topo 0
    display_dir 0
    display_attr 0
    type_point $ptype
    type_line $ltype
    type_boundary $btype
    type_centroid $ctype
    type_area $atype
    type_face 0
    color $xlinecolor
    fcolor $xthemecolor
    width $ptsize
    _use_fcolor 1
    lcolor #000000
    sqlcolor 0
    icon $icon
    size $ptsize
    field $layer
    lfield $layer
    attribute
    xref left
    yref center
    lsize 8
    cat
    where $sqlwhere
    _query_text 0
    _query_edit 1
    _use_where 1
    minreg
    maxreg
    _width 0.1
  End
""")

            # display theme vector map

            grass.run_command('d.vect', map = map, type = type, layer = layer,
                              where = sqlwhere,
                              color = linecolor, fcolor = themecolor, icon = icon, size = ptsize)

            if type in ["line", "boundary"]:
                out(f_psmap, locals(), """\
vlines $map
  type $type
  layer $layer
  where $sqlwhere
  color $linecolor
  label $rangemin - $rangemax
end
""")
            elif type in ["point", "centroid"]:
                out(f_psmap, locals(), """\
vpoints $map
  type $type
  layer $layer
  where $sqlwhere
  color $linecolor
  fcolor $themecolor
  symbol $icon
  label $rangemin - $rangemax
end
""")
            else:
                out(f_psmap, locals(), """\
vareas $map
  layer $layer
  where $sqlwhere
  color $linecolor
  fcolor $themecolor
  label $rangemin - $rangemax
end
""")

            # increment for next theme
            i += 1
            if i == numint:
                color = endcolor
            else:
                color = [a - b for a, b in zip(color, clrstep)]
            line1 -= 4
            line2 -= 4
            line3 -= 4

    #graduated points and line widths thematic mapping

    if themetype in ["graduated_points", "graduated_lines"]:

        #display graduated points/lines by intervals
        if themecalc == "interval":
            out(f_graph, locals(), """\
move 4 87
text Mapped by $numint intervals of $step
""")

            out(f_gisleg, locals(), """\
subtitle - - - {Mapped by $numint intervals of $step}
""")

            out(f_psleg, locals(), """\
text 4% 87% Mapped by $numint intervals of $step
  ref bottom left
end
""")

            msg(locals(), _("Mapped by $numint intervals of $step"))

        # display graduated points/lines for standard deviation units
        if themecalc == "std_deviation":

            out(f_graph, locals(), """\
move 4 87
text Mapped by standard deviation units of $sd (mean = $mean)
""")

            out(f_gisleg, locals(), """\
subtitle - - - {Mapped by standard deviation units of $sd (mean = $mean)}
""")

            out(f_psleg, locals(), """\
text 4% 87% Mapped by standard deviation units of $sd (mean = $mean)
  ref bottom left
end
""")

            msg(locals(), _("Mapped by standard deviation units of $sd (mean = $mean)"))

        # display graduated points/lines for quartiles
        if themecalc == "quartiles":

            out(f_graph, locals(), """\
move 4 87
text Mapped by quartiles (median = $q2)
""")

            out(f_gisleg, locals(), """\
subtitle - - - {Mapped by quartiles (median = $q2)}
""")

            out(f_psleg, locals(), """\
text 4% 87% Mapped by quartiles (median = $q2)
  ref bottom left
end
""")

            msg(locals(), _("Mapped by quartiles (median = $q2)"))

        line1 = 76
        line2 = 75

        out(f_graph, locals(), """\
move 4 83
text Size/width
move 25 83
text Value
move 4 80
text ==============
move 25 80
text ==============
""")

        out(f_psleg, locals(), """\
text 4% 83% Icon size
  ref bottom left
end
text 25% 83% Value
  ref bottom left
end
text 4% 80% ============
  ref bottom left
end
text 25% 80% ============
  ref bottom left
end
""")


        sys.stdout.write("Size/width\tValue\n")
        sys.stdout.write("==========\t=====\n")

        themecolor = pointcolor

        if flag_f:
            linecolor = "none"

        i = numint
        ptsize = maxsize

        while i >= 1:
            if flag_m:
                # math notation
                if i == 1:
                    closebracket = "]"
                    openbracket = "["
                    mincomparison = ">="
                else:
                    closebracket = "]"
                    openbracket = "]"
                    mincomparison = ">"
            else:
                closebracket = "" 
                openbracket = ""
                if i == 1:
                    mincomparison = ">="
                else:
                    mincomparison = ">"

            themecolor = pointcolor

            if flag_f:
                linecolor = "none"

            rangemin = __builtins__.min(breakpoints)
            rangemax = __builtins__.max(breakpoints)

            if not annotations:
                extranote = ""
            else:
                extranote = annotations[i]

            iconsize = int(ptsize / 2)
            lineht = int(ptsize / 4)
            if lineht < 4:
                lineht = 4

            if i < xlower or i >= xupper:
                if themetype == "graduated_lines":
                    out(f_graph, locals(), """\
color $linecolor
""")

                    out(f_gisleg, locals(), """\
line $themecolor $linecolor $ptsize {$openbracket$rangemin - $rangemax$closebracket $extranote}
""")
                else:
                    out(f_graph, locals(), """\
color $themecolor
""")
                    out(f_gisleg, locals(), """\
point $themecolor $linecolor $ptsize {$openbracket$rangemin - $rangemax$closebracket $extranote}
""")

                out(f_graph, locals(), """\
icon + $iconsize 5 $line1
color 0:0:0
move 10 $line2
text $ptsize pts
move 25 $line2
text $openbracket$rangemin - $rangemax$closebracket $extranote
""")
            else:
                if i == xlower:
                    out(f_graph, locals(), """\
color 0:0:0
move 10 $line2
text ...
""")

                    out(f_gisleg, locals(), """\
text - - - ...
""")
                else:
                    # undo future line increment
                    line2 += lineht

            if i < xlower or i >= xupper:
                out(f_psleg, locals(), """\
point 8% $line1%
  color $linecolor
  fcolor $themecolor
  size $iconsize
  symbol $icon
end
text 25% $line1% $openbracket$rangemin - $rangemax$closebracket $extranote
  ref center left
end
""")
            else:
                if i == xlower:
                    out(f_psleg, locals(), """\
text 25% $xline1% ...
   ref center left
end
""")

            sys.stdout.write(subs(locals(), "$ptsize\t\t$openbracket$rangemin - $rangemax$closebracket $extranote\n"))

            if not where:
                sqlwhere = subs(locals(), "$column $mincomparison $rangemin AND $column <= $rangemax")
            else:
                sqlwhere = subs(locals(), "$column $mincomparison $rangemin AND $column <= $rangemax AND $where")

            # update color to database?
            if flag_u:
                sql = subs(locals(), "UPDATE $table SET grassrgb = '$themecolor' WHERE $sqlwhere")
                grass.write_command('db.execute', database = database, driver = driver, stdin = sql)

            # Create group for GIS Manager
            if flag_g:
                # change rgb colors to hex
                xthemecolor = "#%02X%02X%02X" % tuple(__builtins__.map(int,themecolor.split(":")))
                xlinecolor = "#000000"

                # create group entry
                out(f_group, locals(), """\
  _check 1
  Vector $column = $rangemin - $rangemax
    _check 1
    map $map
    display_shape 1
    display_cat 0
    display_topo 0
    display_dir 0
    display_attr 0
    type_point $ptype
    type_line $ltype
    type_boundary $btype
    type_centroid $ctype
    type_area $atype
    type_face 0
    color $xlinecolor
    width $ptsize
    fcolor $xthemecolor
    _use_fcolor 1
    lcolor #000000
    sqlcolor 0
    icon $icon
    size $ptsize
    field $layer
    lfield $layer
    attribute
    xref left
    yref center
    lsize 8
    cat
    where $sqlwhere
    _query_text 0
    _query_edit 1
    _use_where 1
    minreg
    maxreg
    _width 0.1
  End
""")

            #graduates line widths or point sizes

            if themetype == "graduated_lines":
                grass.run_command('d.vect', map = map, type = type, layer = layer,
                                  where = sqlwhere,
                                  color = linecolor, fcolor = themecolor, icon = icon, size = ptsize,
                                  width = ptsize)

            else:
                grass.run_command('d.vect', map = map, type = type, layer = layer,
                                  where = sqlwhere,
                                  color = linecolor, fcolor = themecolor, icon = icon, size = ptsize)

                out(f_psmap, locals(), """\
vpoints $map
  type $type
  layer $layer
  where $sqlwhere
  color $linecolor
  fcolor $themecolor
  symbol $icon
  size $ptsize
  label $rangemin - $rangemax
end
""")

            ptsize -= pointstep

            line1 -= lineht
            line2 -= lineht
            i -= 1

    # Create graphic legend
    f_graph.close()
    if flag_l:
        grass.run_command('d.erase')
        grass.run_command('d.graph', input = tmp_graph)

    # Create group file for GIS Manager
    f_group.write("End\n")
    f_group.close()
    if flag_g:
        shutil.copyfile(tmp_group, "%s.dm" % group)

    # Create ps.map map file
    f_psmap.write("end\n")
    f_psmap.close()
    if psmap:
        shutil.copyfile(tmp_psmap, "%s.psmap" % psmap)

    # Create ps.map legend file
    f_psleg.write("end\n")
    f_psleg.close()
    if psmap:
        shutil.copyfile(tmp_psleg, "%s_legend.psmap" % psmap)

    # Create text file to use with d.graph in GIS Manager
    f_gisleg.close()
    if flag_s:
        tmpdir = os.path.dirname(tmp_gisleg)
        tlegfile = os.path.join(tmpdir, "gismlegend.txt")
        shutil.copyfile(tmp_gisleg, tlegfile)
Ejemplo n.º 43
0
def main():
    map = options["map"]
    layer = options["layer"]
    column = options["column"]
    otable = options["other_table"]
    ocolumn = options["other_column"]
    if options["subset_columns"]:
        scolumns = options["subset_columns"].split(",")
    else:
        scolumns = None

    try:
        f = grass.vector_layer_db(map, layer)
    except CalledModuleError:
        sys.exit(1)

    maptable = f["table"]
    database = f["database"]
    driver = f["driver"]

    if driver == "dbf":
        grass.fatal(_("JOIN is not supported for tables stored in DBF format"))

    if not maptable:
        grass.fatal(
            _("There is no table connected to this map. Unable to join any column."
              ))

    # check if column is in map table
    if column not in grass.vector_columns(map, layer):
        grass.fatal(
            _("Column <%s> not found in table <%s>") % (column, maptable))

    # describe other table
    all_cols_ot = grass.db_describe(otable, driver=driver,
                                    database=database)["cols"]

    # check if ocolumn is on other table
    if ocolumn not in [ocol[0] for ocol in all_cols_ot]:
        grass.fatal(
            _("Column <%s> not found in table <%s>") % (ocolumn, otable))

    # determine columns subset from other table
    if not scolumns:
        # select all columns from other table
        cols_to_add = all_cols_ot
    else:
        cols_to_add = []
        # check if scolumns exists in the other table
        for scol in scolumns:
            found = False
            for col_ot in all_cols_ot:
                if scol == col_ot[0]:
                    found = True
                    cols_to_add.append(col_ot)
                    break
            if not found:
                grass.warning(
                    _("Column <%s> not found in table <%s>") % (scol, otable))

    all_cols_tt = grass.vector_columns(map, int(layer)).keys()

    select = "SELECT $colname FROM $otable WHERE $otable.$ocolumn=$table.$column"
    template = string.Template("UPDATE $table SET $colname=(%s);" % select)

    for col in cols_to_add:
        # skip the vector column which is used for join
        colname = col[0]
        if colname == column:
            continue

        use_len = False
        if len(col) > 2:
            use_len = True
            # Sqlite 3 does not support the precision number any more
            if driver == "sqlite":
                use_len = False
            # MySQL - expect format DOUBLE PRECISION(M,D), see #2792
            elif driver == "mysql" and col[1] == "DOUBLE PRECISION":
                use_len = False

        if use_len:
            coltype = "%s(%s)" % (col[1], col[2])
        else:
            coltype = "%s" % col[1]

        colspec = "%s %s" % (colname, coltype)

        # add only the new column to the table
        if colname not in all_cols_tt:
            try:
                grass.run_command("v.db.addcolumn",
                                  map=map,
                                  columns=colspec,
                                  layer=layer)
            except CalledModuleError:
                grass.fatal(_("Error creating column <%s>") % colname)

        stmt = template.substitute(
            table=maptable,
            column=column,
            otable=otable,
            ocolumn=ocolumn,
            colname=colname,
        )
        grass.debug(stmt, 1)
        grass.verbose(
            _("Updating column <%s> of vector map <%s>...") % (colname, map))
        try:
            grass.write_command("db.execute",
                                stdin=stmt,
                                input="-",
                                database=database,
                                driver=driver)
        except CalledModuleError:
            grass.fatal(_("Error filling column <%s>") % colname)

    # write cmd history
    grass.vector_history(map)

    return 0
Ejemplo n.º 44
0
def main():
    global tmp, sqltmp, tmpname, nuldev, vector, mask_found, rastertmp
    mask_found = False
    rastertmp = False
    #### setup temporary files
    tmp = grass.tempfile()
    sqltmp = tmp + ".sql"
    # we need a random name
    tmpname = grass.basename(tmp)

    nuldev = file(os.devnull, 'w')

    raster = options['raster']
    colprefix = options['column_prefix']
    vector = options['vector']
    layer = options['layer']
    percentile = options['percentile']

    ### 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)

    vector = vs[0]

    rastertmp = "%s_%s" % (vector, tmpname)

    # check the input raster map
    if not grass.find_file(raster, 'cell')['file']:
	grass.fatal(_("Raster map <%s> not found") % raster)

    # check presence of raster MASK, put it aside
    mask_found = bool(grass.find_file('MASK', 'cell')['file'])
    if mask_found:
	grass.message(_("Raster MASK found, temporarily disabled"))
	grass.run_command('g.rename', rast = ('MASK', tmpname + "_origmask"), quiet = True)

    # save current settings:
    grass.use_temp_region()

    # Temporarily aligning region resolution to $RASTER resolution
    # keep boundary settings
    grass.run_command('g.region', align = raster)

    # prepare raster MASK
    if grass.run_command('v.to.rast', input = vector, output = rastertmp,
			 use = 'cat', quiet = True) != 0:
	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, fs = ';', quiet = True)
    cats = []
    for line in p.stdout:
	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 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.'))

    basecols = ['n', 'min', 'max', 'range', 'mean', 'stddev', 'variance', 'cf_var', 'sum']

    # 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]

    # do extended stats?
    if flags['e']:
	# namespace is limited in DBF but the % value is important
	if dbfdriver:
	    perccol = "per" + percentile
	else:
	    perccol = "percentile_" + percentile
	extracols = ['first_quartile', 'median', 'third_quartile'] + [perccol]
    else:
	extracols = []

    addcols = []
    for i in basecols + extracols:
	# check if column already present
	currcolumn = ("%s_%s" % (colprefix, i))
	if dbfdriver:
	    currcolumn = currcolumn[:10]

	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)
	if grass.run_command('v.db.addcolumn', map = vector, columns = addcols) != 0:
	    grass.fatal(_("Adding columns failed. Exiting."))

    # calculate statistics:
    grass.message(_("Processing data (%d categories)...") % number)

    # get rid of any earlier attempts
    grass.try_remove(sqltmp)

    colnames = []
    for var in basecols + extracols:
	colname = '%s_%s' % (colprefix, var)
	if dbfdriver:
	    colname = colname[:10]
	colnames.append(colname)

    ntabcols = len(colnames)

    # do extended stats?
    if flags['e']:
	extstat = 'e'
    else:
	extstat = ""
	
    f = file(sqltmp, 'w')

    # do the stats
    p = grass.pipe_command('r.univar', flags = 't' + 'g' + extstat, map = raster, 
                      zones = rastertmp, percentile = percentile, fs = ';')

    first_line = 1
    for line in p.stdout:
	if first_line:
	    first_line = 0
	    continue

	vars = line.rstrip('\r\n').split(';')

	f.write("UPDATE %s SET" % fi['table'])
	i = 2
	first_var = 1
	for colname in colnames:
	    value = vars[i]
	    # convert nan, +nan, -nan to NULL
	    if value.lower().endswith('nan'):
		value = 'NULL'
	    if not first_var:
		f.write(" , ")
	    else:
		first_var = 0
	    f.write(" %s=%s" % (colname, value))
	    i += 1
	    # skip n_null_cells, mean_of_abs, sum_of_abs
	    if i == 3 or i == 8 or i == 13:
		i += 1

	f.write(" WHERE %s=%s;\n" % (fi['key'], vars[0]))

    p.wait()
    f.close()

    grass.message(_("Updating the database ..."))
    exitcode = grass.run_command('db.execute', input = sqltmp,
				 database = fi['database'], driver = fi['driver'])

    grass.run_command('g.remove', rast = 'MASK', quiet = True, stderr = nuldev)

    if exitcode == 0:
	grass.message((_("Statistics calculated from raster map <%s>") % raster) +
		      (_(" and uploaded to attribute table of vector map <%s>.") % vector))
    else:
	grass.warning(_("Failed to upload statistics to attribute table of vector map <%s>.") % vector)
    
    
    sys.exit(exitcode)