def compute():

    if options["clouds"]:
        region_mask = "region_mask"
        run_command("v.overlay",
                    overwrite=True,
                    ainput=options["region"],
                    binput=options["clouds"],
                    operator="not",
                    output=region_mask)
    else:
        region_mask = options["region"]

    run_command("g.region",
                overwrite=True,
                vector=region_mask,
                align=options["red"])

    run_command("r.mask", overwrite=True, vector=region_mask)

    run_command("i.vi",
                overwrite=True,
                red=options["red"],
                output="ndvi",
                nir=options["nir"])

    p1 = feed_command("r.recode",
                      overwrite=True,
                      input="ndvi",
                      output="ndvi_class",
                      rules="-")
    p1.stdin.write("""-1:0.1:1
0.1:0.5:2
0.5:1:3""")
    p1.stdin.close()
    p1.wait()

    p2 = feed_command("r.colors", map="ndvi_class", rules="-")
    p2.stdin.write("""1 grey
2 255 255 0
3 green""")
    p2.stdin.close()
    p2.wait()

    run_command("r.to.vect",
                flags='sv',
                overwrite=True,
                input="ndvi_class",
                output="ndvi_class",
                type="area")

    run_command("v.clean",
                overwrite=True,
                input="ndvi_class",
                output=options["output"],
                tool="rmarea",
                threshold=options['threshold'])
Beispiel #2
0
def main():
    images = options['input'].split(',')
    output = options['output']

    count = len(images)
    msg = _('Do not forget to set region properly to cover all images.')
    gscript.warning(msg)

    offset = 0
    offsets = []
    parms = {}
    for n, img in enumerate(images):
        offsets.append(offset)
        parms['image%d' % (n + 1)] = img
        parms['offset%d' % (n + 1)] = offset
        offset += get_limit(img) + 1

    gscript.message(_("Mosaicing %d images...") % count)

    gscript.mapcalc("$output = " + make_expression(1, count),
                    output=output,
                    **parms)

    # modify the color table:
    p = gscript.feed_command('r.colors', map=output, rules='-')
    for img, offset in zip(images, offsets):
        print(img, offset)
        copy_colors(p.stdin, img, offset)
    p.stdin.close()
    p.wait()

    gscript.message(_("Done. Raster map <%s> created.") % output)

    # write cmd history:
    gscript.raster_history(output)
Beispiel #3
0
    def save_map(self):
	p = grass.feed_command('r.in.ascii', input = '-', output = self.tempmap, quiet = True, overwrite = True)
	outf = p.stdin
	outf.write("north: %f\n" % self.wind['n'])
	outf.write("south: %f\n" % self.wind['s'])
	outf.write("east: %f\n"  % self.wind['e'])
	outf.write("west: %f\n"  % self.wind['w'])
	outf.write("rows: %d\n"  % self.wind['rows'])
	outf.write("cols: %d\n"  % self.wind['cols'])
	outf.write("null: *\n")

	for row in range(self.wind['rows']):
	    for col in range(self.wind['cols']):
		if col > 0:
		    outf.write(" ")
		val = self.values[row][col]
		if val and self.changed[row][col]:
		    outf.write("%s" % val)
		else:
		    outf.write('*')
	    outf.write("\n")

	outf.close()
	p.wait()

	run('g.region', raster = self.inmap)
	run('r.patch', input = (self.tempmap, self.outmap), output = self.outmap, overwrite = True)
	run('r.colors', map = self.outmap, rast = self.inmap)
	run('g.remove', flags = 'f', type = 'raster', name = self.tempmap)
Beispiel #4
0
def main():
    images = options['input'].split(',')
    output = options['output']

    count = len(images)
    msg = _('Do not forget to set region properly to cover all images.')
    gscript.warning(msg)

    offset = 0
    offsets = []
    parms = {}
    for n, img in enumerate(images):
        offsets.append(offset)
        parms['image%d' % (n + 1)] = img
        parms['offset%d' % (n + 1)] = offset
        offset += get_limit(img) + 1

    gscript.message(_("Mosaicing %d images...") % count)

    gscript.mapcalc("$output = " + make_expression(1, count),
                    output=output, **parms)

    # modify the color table:
    p = gscript.feed_command('r.colors', map=output, rules='-')
    for img, offset in zip(images, offsets):
        print(img, offset)
        copy_colors(p.stdin, img, offset)
    p.stdin.close()
    p.wait()

    gscript.message(_("Done. Raster map <%s> created.") % output)

    # write cmd history:
    gscript.raster_history(output)
Beispiel #5
0
def main():
    input = options['input']
    maskcats = options['maskcats']
    remove = flags['r']
    invert = flags['i']

    if not remove and not input:
	grass.fatal(_("Required parameter <input> not set"))

    #check if input file exists
    if not grass.find_file(input)['file'] and not remove:
        grass.fatal(_("<%s> does not exist.") % input)

    if not 'MASKCATS' in grass.gisenv() and not remove:
        ## beware: next check is made with != , not with 'is', otherwise:
        #>>> grass.raster_info("basin_50K")['datatype'] is "CELL"
        #False
        # even if:
        #>>> "CELL" is "CELL"
        #True 
        if grass.raster_info(input)['datatype'] != "CELL":
            grass.fatal(_("Raster map %s must be integer for maskcats parameter") % input)

    mapset = grass.gisenv()['MAPSET']
    exists = bool(grass.find_file('MASK', element = 'cell', mapset = mapset)['file'])

    if remove:
	if exists:
	    grass.run_command('g.remove', rast = 'MASK')
	    grass.message(_("Raster MASK removed"))
 	else:
	    grass.fatal(_("No existing MASK to remove"))
    else:
	if exists:
            if not grass.overwrite():
                grass.fatal(_("MASK already found in current mapset. Delete first or overwrite."))
            else:
                grass.warning(_("MASK already exists and will be overwritten"))

	p = grass.feed_command('r.reclass', input = input, output = 'MASK', overwrite = True, rules = '-')
	p.stdin.write("%s = 1" % maskcats)
	p.stdin.close()
	p.wait()

	if invert:
	    global tmp
	    tmp = "r_mask_%d" % os.getpid()
	    grass.run_command('g.rename', rast = ('MASK',tmp), quiet = True)
	    grass.mapcalc("MASK=if(isnull($tmp),1,null())", tmp = tmp)
	    grass.run_command('g.remove', rast = tmp, quiet = True)
	    grass.message(_("Inverted MASK created."))
	else:
	    grass.message(_("MASK created."))

        grass.message(_("All subsequent raster operations will be limited to MASK area. ") +
		      "Removing or renaming raster file named MASK will " +
		      "restore raster operations to normal")
Beispiel #6
0
def main():
    table = options['table']
    force = flags['f']

    if not options['driver'] or not options['database']:
        # check if DB parameters are set, and if not set them.
        grass.run_command('db.connect', flags='c', quiet=True)

    kv = grass.db_connection()
    if options['database']:
        database = options['database']
    else:
        database = kv['database']
    if options['driver']:
        driver = options['driver']
    else:
        driver = kv['driver']
    # schema needed for PG?

    if force:
        grass.message(_("Forcing ..."))

    # check if table exists
    if not grass.db_table_exist(table):
        grass.warning(
            _("Table <%s> not found in database <%s>") % (table, database))
        sys.exit(0)

    # check if table is used somewhere (connected to vector map)
    used = grass.db.db_table_in_vector(table)
    if used:
        grass.warning(
            _("Deleting table <%s> which is attached to following map(s):") %
            table)
        for vect in used:
            grass.warning("%s" % vect)

    if not force:
        grass.message(_("The table <%s> would be deleted.") % table)
        grass.message("")
        grass.message(
            _("You must use the force flag to actually remove it. Exiting."))
        sys.exit(0)

    p = grass.feed_command('db.execute',
                           input='-',
                           database=database,
                           driver=driver)
    p.stdin.write(encode("DROP TABLE " + table))
    p.stdin.close()
    p.wait()
    if p.returncode != 0:
        grass.fatal(_("Cannot continue (problem deleting table)."))
Beispiel #7
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)
Beispiel #8
0
def main():
    table = options['table']
    force = flags['f']

    # check if DB parameters are set, and if not set them.
    grass.run_command('db.connect', flags = 'c')

    kv = grass.db_connection()
    database = kv['database']
    driver = kv['driver']
    # schema needed for PG?

    if force:
	grass.message(_("Forcing ..."))

    # check if table exists
    nuldev = file(os.devnull, 'w')
    if not grass.db_table_exist(table, stdout = nuldev, stderr = nuldev):
	grass.fatal(_("Table <%s> not found in current mapset") % table)

    # check if table is used somewhere (connected to vector map)
    used = []
    vects = grass.list_strings('vect')
    for vect in vects:
	for f in grass.vector_db(vect, stderr = nuldev).itervalues():
	    if not f:
		continue
	    if f['table'] == table:
		used.append(vect)
		break
    if used:
	grass.warning(_("Deleting table <%s> which is attached to following map(s):") % table)
	for vect in used:
	    grass.message(vect)

    if not force:
	grass.message(_("The table <%s> would be deleted.") % table)
	grass.message("")
	grass.message(_("You must use the force flag to actually remove it. Exiting."))
	sys.exit(0)

    p = grass.feed_command('db.execute', input = '-', database = database, driver = driver)
    p.stdin.write("DROP TABLE " + table)
    p.stdin.close()
    p.wait()
    if p.returncode != 0:
  	grass.fatal(_("Cannot continue (problem deleting table)."))
Beispiel #9
0
def main():
    table = options['table']
    force = flags['f']

    if not options['driver'] or not options['database']:
        # check if DB parameters are set, and if not set them.
        grass.run_command('db.connect', flags='c')

    kv = grass.db_connection()
    if options['database']:
        database = options['database']
    else:
        database = kv['database']
    if options['driver']:
        driver = options['driver']
    else:
        driver = kv['driver']
    # schema needed for PG?

    if force:
        grass.message(_("Forcing ..."))

    # check if table exists
    if not grass.db_table_exist(table):
        grass.fatal(_("Table <%s> not found in database <%s>") %
                    (table, database))

    # check if table is used somewhere (connected to vector map)
    used = grass.db.db_table_in_vector(table)
    if used:
        grass.warning(_("Deleting table <%s> which is attached to following map(s):") % table)
        for vect in used:
            grass.warning("%s" % vect)

    if not force:
        grass.message(_("The table <%s> would be deleted.") % table)
        grass.message("")
        grass.message(_("You must use the force flag to actually remove it. Exiting."))
        sys.exit(0)

    p = grass.feed_command('db.execute', input='-', database=database,
                           driver=driver)
    p.stdin.write("DROP TABLE " + table)
    p.stdin.close()
    p.wait()
    if p.returncode != 0:
        grass.fatal(_("Cannot continue (problem deleting table)."))
Beispiel #10
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)
Beispiel #11
0
        def save_map(self):
            p = grass.feed_command("r.in.ascii",
                                   input="-",
                                   output=self.tempmap,
                                   quiet=True,
                                   overwrite=True)
            outf = p.stdin
            outf.write(grass.encode("north: %f\n" % self.wind["n"]))
            outf.write(grass.encode("south: %f\n" % self.wind["s"]))
            outf.write(grass.encode("east: %f\n" % self.wind["e"]))
            outf.write(grass.encode("west: %f\n" % self.wind["w"]))
            outf.write(grass.encode("rows: %d\n" % self.wind["rows"]))
            outf.write(grass.encode("cols: %d\n" % self.wind["cols"]))
            outf.write(grass.encode("null: *\n"))

            for row in range(self.wind["rows"]):
                for col in range(self.wind["cols"]):
                    if col > 0:
                        outf.write(grass.encode(" "))
                    val = self.values[row][col]
                    if val and self.changed[row][col]:
                        outf.write(grass.encode("%s" % val))
                    else:
                        outf.write(grass.encode("*"))
                outf.write(grass.encode("\n"))

            outf.close()
            p.wait()

            run("g.region", raster=self.inmap)
            run(
                "r.patch",
                input=(self.tempmap, self.outmap),
                output=self.outmap,
                overwrite=True,
            )
            run("r.colors", map=self.outmap, rast=self.inmap)
            run("g.remove", flags="f", type="raster", name=self.tempmap)
Beispiel #12
0
 def write_stations_snapped(self):
     """Write out the stations_snapped to a vector."""
     types = {'i': 'int', 'f': 'double'}
     # columns
     cols = self.stations_snapped_columns
     cols_dt = [' '.join([i, types[cols[i].dtype.kind]]) for i in cols.keys()]
     cols_fmt = '|'.join(['%'+cols[i].dtype.kind for i in cols.keys()])
     data = np.column_stack(cols.values())
     # create vector if needed
     p = grass.feed_command('v.in.ascii', input='-', x=3, y=4, cat=1, quiet=True,
                            columns=cols_dt, output=self.stations_snapped)
     np.savetxt(p.stdin, data, delimiter='|', fmt=cols_fmt)
     p.stdin.close()
     p.wait()
     # drop x y columns
     grun('v.db.dropcolumn', map=self.stations_snapped, columns='x,y')
     # add other columns
     cat = grass.vector_info(self.stations_snapped)['attribute_primary_key']
     grun('g.copy', vector=self.stations+',stations__tmp', quiet=True)
     catother = grass.vector_info('stations__tmp')['attribute_primary_key']
     grun('v.db.join', map=self.stations_snapped, column=cat,
          other_table='stations__tmp', other_column=catother, quiet=True)
     return
Beispiel #13
0
def main():
    global temp_dist, temp_src

    input = options["input"]
    output = options["output"]
    distances = options["distances"]
    units = options["units"]
    zero = flags["z"]

    tmp = str(os.getpid())
    temp_dist = "r.buffer.tmp.%s.dist" % tmp
    temp_src = "r.buffer.tmp.%s.src" % tmp

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

    scale = scales[units]

    distances = distances.split(",")
    distances1 = [scale * float(d) for d in distances]
    distances2 = [d * d for d in distances1]

    s = grass.read_command("g.proj", flags="j")
    kv = grass.parse_key_val(s)
    if kv["+proj"] == "longlat":
        metric = "geodesic"
    else:
        metric = "squared"

    grass.run_command("r.grow.distance",
                      input=input,
                      metric=metric,
                      distance=temp_dist,
                      flags="m")

    if zero:
        exp = "$temp_src = if($input == 0,null(),1)"
    else:
        exp = "$temp_src = if(isnull($input),null(),1)"

    grass.message(_("Extracting buffers (1/2)..."))
    grass.mapcalc(exp, temp_src=temp_src, input=input)

    exp = "$output = if(!isnull($input),$input,%s)"
    if metric == "squared":
        for n, dist2 in enumerate(distances2):
            exp %= "if($dist <= %f,%d,%%s)" % (dist2, n + 2)
    else:
        for n, dist2 in enumerate(distances1):
            exp %= "if($dist <= %f,%d,%%s)" % (dist2, n + 2)
    exp %= "null()"

    grass.message(_("Extracting buffers (2/2)..."))
    grass.mapcalc(exp, output=output, input=temp_src, dist=temp_dist)

    p = grass.feed_command("r.category", map=output, separator=":", rules="-")
    msg = "1:distances calculated from these locations\n"
    p.stdin.write(encode(msg))
    d0 = "0"
    for n, d in enumerate(distances):
        msg = "%d:%s-%s %s\n" % (n + 2, d0, d, units)
        p.stdin.write(encode(msg))
        d0 = d
    p.stdin.close()
    p.wait()

    grass.run_command("r.colors", map=output, color="rainbow")

    # write cmd history:
    grass.raster_history(output)
Beispiel #14
0
def main():
    if not hasNumPy:
        grass.fatal(_("Required dependency NumPy not found. Exiting."))

    sharpen = options['method']  # sharpening algorithm
    ms1_orig = options['blue']  # blue channel
    ms2_orig = options['green']  # green channel
    ms3_orig = options['red']  # red channel
    pan_orig = options['pan']  # high res pan channel
    out = options['output']  # prefix for output RGB maps
    bits = options['bitdepth']  # bit depth of image channels
    bladjust = flags['l']  # adjust blue channel
    sproc = flags['s']  # serial processing
    rescale = flags[
        'r']  # rescale to spread pixel values to entire 0-255 range

    # Checking bit depth
    bits = float(bits)
    if bits < 2 or bits > 30:
        grass.warning(_("Bit depth is outside acceptable range"))
        return

    outb = grass.core.find_file('%s_blue' % out)
    outg = grass.core.find_file('%s_green' % out)
    outr = grass.core.find_file('%s_red' % out)

    if (outb['name'] != '' or outg['name'] != ''
            or outr['name'] != '') and not grass.overwrite():
        grass.warning(
            _('Maps with selected output prefix names already exist.'
              ' Delete them or use overwrite flag'))
        return

    pid = str(os.getpid())

    # convert input image channels to 8 bit for processing
    ms1 = 'tmp%s_ms1' % pid
    ms2 = 'tmp%s_ms2' % pid
    ms3 = 'tmp%s_ms3' % pid
    pan = 'tmp%s_pan' % pid

    if rescale == False:
        if bits == 8:
            grass.message(_("Using 8bit image channels"))
            if sproc:
                # serial processing
                grass.run_command('g.copy',
                                  raster='%s,%s' % (ms1_orig, ms1),
                                  quiet=True,
                                  overwrite=True)
                grass.run_command('g.copy',
                                  raster='%s,%s' % (ms2_orig, ms2),
                                  quiet=True,
                                  overwrite=True)
                grass.run_command('g.copy',
                                  raster='%s,%s' % (ms3_orig, ms3),
                                  quiet=True,
                                  overwrite=True)
                grass.run_command('g.copy',
                                  raster='%s,%s' % (pan_orig, pan),
                                  quiet=True,
                                  overwrite=True)
            else:
                # parallel processing
                pb = grass.start_command('g.copy',
                                         raster='%s,%s' % (ms1_orig, ms1),
                                         quiet=True,
                                         overwrite=True)
                pg = grass.start_command('g.copy',
                                         raster='%s,%s' % (ms2_orig, ms2),
                                         quiet=True,
                                         overwrite=True)
                pr = grass.start_command('g.copy',
                                         raster='%s,%s' % (ms3_orig, ms3),
                                         quiet=True,
                                         overwrite=True)
                pp = grass.start_command('g.copy',
                                         raster='%s,%s' % (pan_orig, pan),
                                         quiet=True,
                                         overwrite=True)

                pb.wait()
                pg.wait()
                pr.wait()
                pp.wait()

        else:
            grass.message(_("Converting image chanels to 8bit for processing"))
            maxval = pow(2, bits) - 1
            if sproc:
                # serial processing
                grass.run_command('r.rescale',
                                  input=ms1_orig,
                                  from_='0,%f' % maxval,
                                  output=ms1,
                                  to='0,255',
                                  quiet=True,
                                  overwrite=True)
                grass.run_command('r.rescale',
                                  input=ms2_orig,
                                  from_='0,%f' % maxval,
                                  output=ms2,
                                  to='0,255',
                                  quiet=True,
                                  overwrite=True)
                grass.run_command('r.rescale',
                                  input=ms3_orig,
                                  from_='0,%f' % maxval,
                                  output=ms3,
                                  to='0,255',
                                  quiet=True,
                                  overwrite=True)
                grass.run_command('r.rescale',
                                  input=pan_orig,
                                  from_='0,%f' % maxval,
                                  output=pan,
                                  to='0,255',
                                  quiet=True,
                                  overwrite=True)

            else:
                # parallel processing
                pb = grass.start_command('r.rescale',
                                         input=ms1_orig,
                                         from_='0,%f' % maxval,
                                         output=ms1,
                                         to='0,255',
                                         quiet=True,
                                         overwrite=True)
                pg = grass.start_command('r.rescale',
                                         input=ms2_orig,
                                         from_='0,%f' % maxval,
                                         output=ms2,
                                         to='0,255',
                                         quiet=True,
                                         overwrite=True)
                pr = grass.start_command('r.rescale',
                                         input=ms3_orig,
                                         from_='0,%f' % maxval,
                                         output=ms3,
                                         to='0,255',
                                         quiet=True,
                                         overwrite=True)
                pp = grass.start_command('r.rescale',
                                         input=pan_orig,
                                         from_='0,%f' % maxval,
                                         output=pan,
                                         to='0,255',
                                         quiet=True,
                                         overwrite=True)

                pb.wait()
                pg.wait()
                pr.wait()
                pp.wait()

    else:
        grass.message(_("Rescaling image chanels to 8bit for processing"))

        min_ms1 = int(grass.raster_info(ms1_orig)['min'])
        max_ms1 = int(grass.raster_info(ms1_orig)['max'])
        min_ms2 = int(grass.raster_info(ms2_orig)['min'])
        max_ms2 = int(grass.raster_info(ms2_orig)['max'])
        min_ms3 = int(grass.raster_info(ms3_orig)['min'])
        max_ms3 = int(grass.raster_info(ms3_orig)['max'])
        min_pan = int(grass.raster_info(pan_orig)['min'])
        max_pan = int(grass.raster_info(pan_orig)['max'])

        maxval = pow(2, bits) - 1
        if sproc:
            # serial processing
            grass.run_command('r.rescale',
                              input=ms1_orig,
                              from_='%f,%f' % (min_ms1, max_ms1),
                              output=ms1,
                              to='0,255',
                              quiet=True,
                              overwrite=True)
            grass.run_command('r.rescale',
                              input=ms2_orig,
                              from_='%f,%f' % (min_ms2, max_ms2),
                              output=ms2,
                              to='0,255',
                              quiet=True,
                              overwrite=True)
            grass.run_command('r.rescale',
                              input=ms3_orig,
                              from_='%f,%f' % (min_ms3, max_ms3),
                              output=ms3,
                              to='0,255',
                              quiet=True,
                              overwrite=True)
            grass.run_command('r.rescale',
                              input=pan_orig,
                              from_='%f,%f' % (min_pan, max_pan),
                              output=pan,
                              to='0,255',
                              quiet=True,
                              overwrite=True)

        else:
            # parallel processing
            pb = grass.start_command('r.rescale',
                                     input=ms1_orig,
                                     from_='%f,%f' % (min_ms1, max_ms1),
                                     output=ms1,
                                     to='0,255',
                                     quiet=True,
                                     overwrite=True)
            pg = grass.start_command('r.rescale',
                                     input=ms2_orig,
                                     from_='%f,%f' % (min_ms2, max_ms2),
                                     output=ms2,
                                     to='0,255',
                                     quiet=True,
                                     overwrite=True)
            pr = grass.start_command('r.rescale',
                                     input=ms3_orig,
                                     from_='%f,%f' % (min_ms3, max_ms3),
                                     output=ms3,
                                     to='0,255',
                                     quiet=True,
                                     overwrite=True)
            pp = grass.start_command('r.rescale',
                                     input=pan_orig,
                                     from_='%f,%f' % (min_pan, max_pan),
                                     output=pan,
                                     to='0,255',
                                     quiet=True,
                                     overwrite=True)

            pb.wait()
            pg.wait()
            pr.wait()
            pp.wait()

    # get PAN resolution:
    kv = grass.raster_info(map=pan)
    nsres = kv['nsres']
    ewres = kv['ewres']
    panres = (nsres + ewres) / 2

    # clone current region
    grass.use_temp_region()
    grass.run_command('g.region', res=panres, align=pan)

    # Select sharpening method
    grass.message(
        _("Performing pan sharpening with hi res pan image: %f" % panres))
    if sharpen == "brovey":
        brovey(pan, ms1, ms2, ms3, out, pid, sproc)
    elif sharpen == "ihs":
        ihs(pan, ms1, ms2, ms3, out, pid, sproc)
    elif sharpen == "pca":
        pca(pan, ms1, ms2, ms3, out, pid, sproc)
    # Could add other sharpening algorithms here, e.g. wavelet transformation

    grass.message(
        _("Assigning grey equalized color tables to output images..."))

    # equalized grey scales give best contrast
    grass.message(_("setting pan-sharpened channels to equalized grey scale"))
    for ch in ['red', 'green', 'blue']:
        grass.run_command('r.colors',
                          quiet=True,
                          map="%s_%s" % (out, ch),
                          flags="e",
                          color='grey')

    # Landsat too blue-ish because panchromatic band less sensitive to blue
    # light, so output blue channed can be modified
    if bladjust:
        grass.message(_("Adjusting blue channel color table..."))
        blue_colors = ['0 0 0 0\n5% 0 0 0\n67% 255 255 255\n100% 255 255 255']
        # these previous colors are way too blue for landsat
        # blue_colors = ['0 0 0 0\n10% 0 0 0\n20% 200 200 200\n40% 230 230 230\n67% 255 255 255\n100% 255 255 255']
        bc = grass.feed_command('r.colors',
                                quiet=True,
                                map="%s_blue" % out,
                                rules="-")
        bc.stdin.write('\n'.join(blue_colors))
        bc.stdin.close()

    # output notice
    grass.verbose(
        _("The following pan-sharpened output maps have been generated:"))
    for ch in ['red', 'green', 'blue']:
        grass.verbose(_("%s_%s") % (out, ch))

    grass.verbose(
        _("To visualize output, run: g.region -p raster=%s_red" % out))
    grass.verbose(_("d.rgb r=%s_red g=%s_green b=%s_blue" % (out, out, out)))
    grass.verbose(
        _("If desired, combine channels into a single RGB map with 'r.composite'."
          ))
    grass.verbose(
        _("Channel colors can be rebalanced using i.colors.enhance."))

    # write cmd history:
    for ch in ['red', 'green', 'blue']:
        grass.raster_history("%s_%s" % (out, ch))

    # create a group with the three outputs
    #grass.run_command('i.group', group=out,
    #                  input="{n}_red,{n}_blue,{n}_green".format(n=out))

    # Cleanup
    grass.message(_("cleaning up temp files"))
    try:
        grass.run_command('g.remove',
                          flags="f",
                          type="raster",
                          pattern="tmp%s*" % pid,
                          quiet=True)
    except:
        ""
Beispiel #15
0
def calculate_lfp(input, output, idcol, id, coords, outlet, layer,
                  outletidcol):
    prefix = "r_lfp_%d_" % os.getpid()

    if id:
        ids = id.split(",")
        for i in range(0, len(ids)):
            try:
                ids[i] = int(ids[i])
            except:
                grass.fatal(_("Invalid ID '%s'") % ids[i])
    else:
        ids = []

    if coords:
        coords = coords.split(",")
    else:
        coords = []

    # append outlet points to coordinates
    if outlet:
        p = grass.pipe_command("v.report",
                               map=outlet,
                               layer=layer,
                               option="coor")
        for line in p.stdout:
            line = line.rstrip("\n")
            if line.startswith("cat|"):
                colnames = line.split("|")
                outletid_ind = -1
                for i in range(0, len(colnames)):
                    colname = colnames[i]
                    if colname == outletidcol:
                        outletid_ind = i
                    elif colname == "x":
                        x_ind = i
                    elif colname == "y":
                        y_ind = i
                if outletidcol and outletid_ind == -1:
                    grass.fatal(
                        _("Cannot find column <%s> in vector map <%s>") %
                        (outletidcol, outlet))
                continue
            cols = line.split("|")
            coords.extend([cols[x_ind], cols[y_ind]])
            if outletid_ind >= 0:
                try:
                    ids.extend([int(cols[outletid_ind])])
                except:
                    grass.fatal(_("Invalid ID '%s'") % ids[i])
        p.wait()
        if p.returncode != 0:
            grass.fatal(_("Cannot read outlet points"))

    if len(ids) > 0:
        if len(ids) > len(coords) / 2:
            grass.fatal(_("Too many IDs"))
        elif len(ids) < len(coords) / 2:
            grass.fatal(_("Too few IDs"))
        assign_id = True
    else:
        assign_id = False

    # create the output vector map
    try:
        grass.run_command("v.edit", map=output, tool="create")
    except CalledModuleError:
        grass.fatal(_("Cannot create the output vector map"))

    if assign_id:
        try:
            grass.run_command("v.db.addtable",
                              map=output,
                              columns="%s integer" % idcol)
        except CalledModuleError:
            grass.fatal(_("Cannot add a table to the output vector map"))

    for i in range(0, len(coords) / 2):
        cat = i + 1
        coor = "%s,%s" % (coords[2 * i], coords[2 * i + 1])
        if assign_id:
            id = ids[i]
            grass.message(_("Processing outlet %d at %s...") % (id, coor))
        else:
            grass.message(_("Processing outlet at %s...") % coor)

        # create the outlet vector map
        out = prefix + "out"
        p = grass.feed_command("v.in.ascii",
                               overwrite=True,
                               input="-",
                               output=out,
                               separator=",")
        p.stdin.write(coor)
        p.stdin.close()
        p.wait()
        if p.returncode != 0:
            grass.fatal(_("Cannot create the outlet vector map"))

        # convert the outlet vector map to raster
        try:
            grass.run_command("v.to.rast",
                              overwrite=True,
                              input=out,
                              output=out,
                              use="cat",
                              type="point")
        except CalledModuleError:
            grass.fatal(_("Cannot convert the outlet vector to raster"))

        # calculate the downstream flow length
        flds = prefix + "flds"
        try:
            grass.run_command("r.stream.distance",
                              overwrite=True,
                              flags="om",
                              stream_rast=out,
                              direction=input,
                              method="downstream",
                              distance=flds)
        except CalledModuleError:
            grass.fatal(_("Cannot calculate the downstream flow length"))

        # find the longest flow length
        p = grass.pipe_command("r.info", flags="r", map=flds)
        max = ""
        for line in p.stdout:
            line = line.rstrip("\n")
            if line.startswith("max="):
                max = line.split("=")[1]
                break
        p.wait()
        if p.returncode != 0 or max == "":
            grass.fatal(_("Cannot find the longest flow length"))

        threshold = float(max) - 0.0005

        # find the headwater cells
        heads = prefix + "heads"
        try:
            grass.run_command("r.mapcalc",
                              overwrite=True,
                              expression="%s=if(%s>=%f,1,null())" %
                              (heads, flds, threshold))
        except CalledModuleError:
            grass.fatal(_("Cannot find the headwater cells"))

        # create the headwater vector map
        try:
            grass.run_command("r.to.vect",
                              overwrite=True,
                              input=heads,
                              output=heads,
                              type="point")
        except CalledModuleError:
            grass.fatal(_("Cannot create the headwater vector map"))

        # calculate the longest flow path in vector format
        path = prefix + "path"
        try:
            grass.run_command("r.path",
                              overwrite=True,
                              input=input,
                              vector_path=path,
                              start_points=heads)
        except CalledModuleError:
            grass.fatal(_("Cannot create the longest flow path vector map"))

        # snap the outlet
        try:
            grass.run_command("r.to.vect",
                              overwrite=True,
                              input=out,
                              output=out,
                              type="point")
        except CalledModuleError:
            grass.fatal(_("Cannot snap the outlet"))

        # find the coordinates of the snapped outlet
        p = grass.pipe_command("v.to.db", flags="p", map=out, option="coor")
        coor = ""
        for line in p.stdout:
            line = line.rstrip("\n")
            if line == "cat|x|y|z":
                continue
            cols = line.split("|")
            coor = "%s,%s" % (cols[1], cols[2])
        p.wait()
        if p.returncode != 0 or coor == "":
            grass.fatal(_("Cannot find the coordinates of the snapped outlet"))

        # split the longest flow path at the outlet
        try:
            grass.run_command("v.edit", map=path, tool="break", coords=coor)
        except CalledModuleError:
            grass.fatal(_("Cannot split the longest flow path at the outlet"))

        # select the final longest flow path
        lfp = prefix + "lfp"
        try:
            grass.run_command("v.select",
                              overwrite=True,
                              ainput=path,
                              binput=heads,
                              output=lfp)
        except CalledModuleError:
            grass.fatal(_("Cannot select the final longest flow path"))

        lfp2 = lfp + "2"
        try:
            grass.run_command("v.category",
                              overwrite=True,
                              input=lfp,
                              output=lfp2,
                              option="del",
                              cat=-1)
            grass.run_command("v.category",
                              overwrite=True,
                              input=lfp2,
                              output=lfp,
                              option="add",
                              cat=cat,
                              step=0)
        except CalledModuleError:
            grass.fatal(_("Cannot add category %d") % cat)

        # copy the final longest flow path to the output map
        try:
            grass.run_command("v.edit",
                              flags="r",
                              map=output,
                              tool="copy",
                              bgmap=lfp,
                              cats=0)
        except CalledModuleError:
            grass.fatal(_("Cannot copy the final longest flow path"))

        if assign_id:
            try:
                grass.run_command("v.to.db",
                                  map=output,
                                  option="cat",
                                  columns="cat")
                grass.run_command("v.db.update",
                                  map=output,
                                  column=idcol,
                                  value=id,
                                  where="cat=%d" % cat)
            except CalledModuleError:
                grass.fatal(_("Cannot assign ID %d") % id)

    # remove intermediate outputs
    grass.run_command("g.remove",
                      flags="f",
                      type="raster,vector",
                      pattern="%s*" % prefix)

    # write history if supported
    version = grass.version()
    if version["revision"] != "exported":
        # the revision number is available
        version = int(version["revision"][1:])
    else:
        # some binary distributions don't build from the SVN repository and
        # revision is not available; use the libgis revision as a fallback in
        # this case
        version = int(version["libgis_revision"])

    if version >= 70740:
        # v.support -h added in r70740
        grass.run_command("v.support",
                          flags="h",
                          map=output,
                          cmdhist=os.environ["CMDLINE"])
Beispiel #16
0
def main():
    global tmp, tmp_proj, tmp_gpx, tmp_extr, tmp_vogb

    format = options['format']
    input = options['input']
    layer = options['layer']
    output = options['output']
    type = options['type']
    where = options['where']
    wpt = flags['w']
    rte = flags['r']
    trk = flags['t']

    nflags = len(filter(None, [wpt, rte, trk]))
    if nflags > 1:
	grass.fatal(_("One feature at a time please."))
    if nflags < 1:
	grass.fatal(_("No features requested for export."))

    # set some reasonable defaults
    if not type:
	if wpt:
	    type = 'point'
	else:
	    type = 'line'

    #### check for gpsbabel
    ### FIXME: may need --help or similar?
    if not grass.find_program("gpsbabel"):
	grass.fatal(_("The gpsbabel program was not found, please install it first.\n") +
		    "http://gpsbabel.sourceforge.net")

    #### check for cs2cs
    if not grass.find_program("cs2cs"):
	grass.fatal(_("The cs2cs program was not found, please install it first.\n") +
		    "http://proj.osgeo.org")

    # check if we will overwrite data
    if os.path.exists(output) and not grass.overwrite():
	grass.fatal(_("Output file already exists."))

    #### set temporary files
    tmp = grass.tempfile()

    # SQL extract if needed
    if where:
	grass.verbose("Extracting data ...")
	tmp_extr = "tmp_vogb_extr_%d" % os.getpid()
	ret = grass.run_command('v.extract', input = "$GIS_OPT_INPUT",
				output = tmp_extr, type = type, layer = layer,
				where = where, quiet = True)
	if ret != 0:
	    grass.fatal(_("Error executing SQL query"))

	kv = grass.vector_info_topo(tmp_extr)
	if kv['primitives'] == 0:
	    grass.fatal(_("SQL query returned an empty map (no %s features?)") % type)

	inmap = tmp_extr
    else:
	#   g.copy "$GIS_OPT_INPUT,tmp_vogb_extr_$$"   # to get a copy of DB into local mapset
	#   INMAP="tmp_vogb_extr_$$"
	inmap = input

    #### set up projection info
    # TODO: check if we are already in ll/WGS84.  If so skip m.proj step.

    # TODO: multi layer will probably fail badly due to sed 's/^ 1   /'
    #   output as old GRASS 4 vector ascii and fight with dig_ascii/?
    #   Change to s/^ \([0-9]   .*\)    /# \1/' ??? mmph.

    # reproject to lat/lon WGS84
    grass.verbose("Reprojecting data ...")

    re1 = re.compile(r'^\([PLBCFKA]\)')
    re2 = re.compile(r'^ 1     ')

    re3 = re.compile(r'\t\([-\.0-9]*\) .*')
    re4 = re.compile(r'^\([-\.0-9]\)')
    re5 = re.compile(r'^#')

    tmp_proj = tmp + ".proj"
    tf = open(tmp_proj, 'w')
    p1 = grass.pipe_command('v.out.ascii', input = inmap, format = 'standard')
    p2 = grass.feed_command('m.proj', input = '-', flags = 'od', quiet = True, stdout = tf)
    tf.close()

    lineno = 0
    for line in p1.stdout:
	lineno += 1
	if lineno < 11:
	    continue
	line = re1.sub(r'#\1', line)
	line = re2.sub(r'# 1  ', line)
	p2.stdin.write(line)

    p2.stdin.close()
    p1.wait()
    p2.wait()

    if p1.returncode != 0 or p2.returncode != 0:
	grass.fatal(_("Error reprojecting data"))

    tmp_vogb = "tmp_vogb_epsg4326_%d" % os.getpid()
    p3 = grass.feed_command('v.in.ascii', out = tmp_vogb, format = 'standard', flags = 'n', quiet = True)
    tf = open(tmp_proj, 'r')

    for line in tf:
	line = re3.sub(r' \1', line)
	line = re4.sub(r' \1', line)
	line = re5.sub('', line)
	p3.stdin.write(line)

    p3.stdin.close()
    tf.close()
    p3.wait()

    if p3.returncode != 0:
	grass.fatal(_("Error reprojecting data"))

    # don't v.db.connect directly as source table will be removed with
    # temporary map in that case. So we make a temp copy of it to work with.
    kv = vector_db(inmap)
    if layer in kv:
	db_params = kv[layer]

	db_table = db_params['table']
	db_key = db_params['key']
	db_database = db_params['database']
	db_driver = db_params['driver']

	ret = grass.run_command('db.copy',
				from_driver = db_driver,
				from_database = db_database,
				from_table = db_table,
				to_table = tmp_vogb)
	if ret != 0:
	    grass.fatal(_("Error copying temporary DB"))

	ret = grass.run_command('v.db.connect', map = tmp_vogb, table = tmp_vogb, quiet = True)
	if ret != 0:
	    grass.fatal(_("Error reconnecting temporary DB"))

    # export as GPX using v.out.ogr
    if trk:
	linetype = "FORCE_GPX_TRACK=YES"
    elif rte:
	linetype = "FORCE_GPX_TRACK=YES"
    else:
	linetype = None

    # BUG: cat is being reported as evelation and attribute output is skipped.
    #   (v.out.ogr DB reading or ->OGR GPX driver bug<-
    #     resolved: see new Create opts at http://www.gdal.org/ogr/drv_gpx.html)
    #   v.out.ogr -> shapefile -> GPX works, but we try to avoid that as it's
    #     lossy. Also that would allow ogr2ogr -a_srs $IN_PROJ -t_srs EPSG:4326
    #     so skip m.proj pains.. if that is done ogr2ogr -s_srs MUST HAVE +wktext
    #     with PROJ.4 terms or else the +nadgrids will be ignored! best to feed
    #     it  IN_PROJ="`g.proj -jf` +wktext"  in that case.

    grass.verbose("Exporting data ...")

    tmp_gpx = tmp + ".gpx"
    ret = grass.run_command('v.out.ogr', input = tmp_vogb, dsn = tmp_gpx,
			    type = type, format = 'GPX', lco = linetype,
			    dsco = "GPX_USE_EXTENSIONS=YES", quiet = True)
    if ret != 0:
	grass.fatal(_("Error exporting data"))

    if format == 'gpx':
	# short circuit, we have what we came for.
	grass.try_remove(output)
	os.rename(tmp_gpx, output)
	grass.verbose("Fast exit.")
	sys.exit()

    # run gpsbabel
    if wpt:
	gtype = '-w'
    elif trk:
	gtype = '-t'
    elif rte:
	gtype = '-r'
    else:
	gtype = ''

    grass.verbose("Running GPSBabel ...")

    ret = grass.call(['gpsbabel',
		      gtype,
		      '-i', 'gpx',
		      '-f', tmp + '.gpx',
		      '-o', format,
		      '-F', output])

    if ret != 0:
	grass.fatal(_("Error running GPSBabel"))

    grass.verbose("Done.")
Beispiel #17
0
def main():
    options, flags = grass.parser()
    xAmap = options["xaraster"]
    xBmap = options["xbraster"]
    yAmap = options["yaraster"]
    yBmap = options["ybraster"]
    output_basename = options["output"]
    custom_threshold = options["custom_threshold"]
    stat_threshold = options["stat_threshold"]
    Xdelta_name = "deltaX"
    Ydelta_name = "deltaY"
    anglemap_name = output_basename + "_angle"
    anglemap_class = anglemap_name + "_class"
    magnitudemap_name = output_basename + "_magnitude"
    changemap_name = output_basename + "_change"

    # Checking that the input maps exist
    if not grass.find_file(name=xAmap, element="cell")["file"]:
        grass.fatal("xaraster map <%s> not found" % xAmap)
    if not grass.find_file(name=xBmap, element="cell")["file"]:
        grass.fatal("xbraster map <%s> not found" % xBmap)
    if not grass.find_file(name=yAmap, element="cell")["file"]:
        grass.fatal("yaraster map <%s> not found" % yAmap)
    if not grass.find_file(name=xBmap, element="cell")["file"]:
        grass.fatal("ybraster map <%s> not found" % yBmap)

    TMPRAST.append(Xdelta_name)
    TMPRAST.append(Ydelta_name)

    # Calculating delta for X and Y bands
    grass.message(_("Calculating DeltaX and DeltaY"))
    delta_calculation(Xdelta_name, xBmap, xAmap)
    delta_calculation(Ydelta_name, yBmap, yAmap)

    # Calculating angle and magnitude maps
    grass.message(_("Writing angle map %s") % anglemap_name)
    angle_calculation(anglemap_name, Xdelta_name, Ydelta_name)

    grass.message(_("Writing magnitude map %s") % magnitudemap_name)
    magnitude_calculation(magnitudemap_name, Xdelta_name, Ydelta_name)

    # Reclassifing angle map to get a map with the four quadrants
    keys = ["1", "2", "3", "4"]
    vals = [0, 90, 180, 270, 360]
    rvals = [(int(vals[i - 1]), int(vals[i]), keys[i - 1], vals[i - 1],
              vals[i]) for i in range(1, len(vals))]
    rules = "\n".join(["%3d thru %3d = %s   %s-%s" % v for v in rvals])
    script.write_command(
        "r.reclass",
        input=anglemap_name,
        output=anglemap_class,
        rules="-",
        overwrite=True,
        stdin=rules.encode(),
    )

    # Generating the change detection map using the given threshold
    if custom_threshold:
        threshold = custom_threshold
        grass.message(_("Threshold is %s") % threshold)
        grass.message(_("Writing change detection map %s") % changemap_name)
        # Creating the final map of the change, using a custom threshold
        change_map_calculation(changemap_name, magnitudemap_name, threshold,
                               anglemap_class)
    elif stat_threshold:
        # Getting values of mean and standard dev of magnitude to calculate the change detection criteria (> mean + N*stdev)
        univar = grass.read_command("r.univar",
                                    map=magnitudemap_name,
                                    flags="g")

        found = 0
        for line in univar.splitlines():
            name, val = line.split("=")
            if name == "mean":
                grass.message(_("Mean of magnitude values is: %s") % val)
                mean = val
                found += 1
            if name == "stddev":
                grass.message(
                    _("Standard deviation of magnitude values is: %s") % val)
                stddev = val
                found += 1
        if found != 2:
            grass.fatal("Couldn't find mean or stddev!")

        adding_value = float(stat_threshold) * float(stddev)
        threshold = float(mean) + float(adding_value)
        grass.message(_("Threshold is %s") % threshold)
        # Creating the final map of the change, using a statistical threshold
        change_map_calculation(changemap_name, magnitudemap_name, threshold,
                               anglemap_class)
    else:
        grass.message(
            _("No threshold given, only angle and magnitude maps have been created"
              ))

    # anglemap_class: set colors
    iva_colors = "1 217 255 0\n2 10 214 10\n3 75 173 255\n4 139 105 20\nnv 255 255 255\ndefault 255 255 255"
    p = grass.feed_command("r.colors", map=anglemap_class, rules="-")
    p.stdin.write(iva_colors.encode())
    p.stdin.close()

    # anglemap_class: set categories
    rules = [
        "1:moisture reduction",
        "2:chlorophyll increase",
        "3:moisture increase",
        "4:bare soil increase",
    ]
    p = grass.feed_command("r.category",
                           map=anglemap_class,
                           rules="-",
                           separator=":")
    p.stdin.write(("\n".join(rules)).encode())
    p.stdin.close()

    return 0
def main():
    """Do the main processing
    """

    # Parse input options:
    patch_map = options['input']
    patches = patch_map.split('@')[0]
    patches_mapset = patch_map.split('@')[1] if len(
        patch_map.split('@')) > 1 else None
    pop_proxy = options['pop_proxy']
    layer = options['layer']
    costs = options['costs']
    cutoff = float(options['cutoff'])
    border_dist = int(options['border_dist'])
    conefor_dir = options['conefor_dir']
    memory = int(options['memory'])

    # Parse output options:
    prefix = options['prefix']
    edge_map = '{}_edges'.format(prefix)
    vertex_map = '{}_vertices'.format(prefix)
    shortest_paths = '{}_shortest_paths'.format(prefix)

    # Parse flags:
    p_flag = flags['p']
    t_flag = flags['t']
    r_flag = flags['r']

    dist_flags = 'kn' if flags['k'] else 'n'

    lin_cat = 1
    zero_dist = None

    folder = grass.tempdir()
    if not os.path.exists(folder):
        os.makedirs(folder)

    # Setup counter for progress message
    counter = 0

    # Check if location is lat/lon (only in lat/lon geodesic distance
    # measuring is supported)
    if grass.locn_is_latlong():
        grass.verbose("Location is lat/lon: Geodesic distance \
                      measure is used")

    # Check if prefix is legal GRASS name
    if not grass.legal_name(prefix):
        grass.fatal('{} is not a legal name for GRASS \
                    maps.'.format(prefix))

    if prefix[0].isdigit():
        grass.fatal('Tables names starting with a digit are not SQL \
                    compliant.'.format(prefix))

    # Check if output maps not already exists or could be overwritten
    for output in [edge_map, vertex_map, shortest_paths]:
        if grass.db.db_table_exist(output) and not grass.overwrite():
            grass.fatal('Vector map <{}> already exists'.format(output))

    # Check if input has required attributes
    in_db_connection = grass.vector.vector_db(patch_map)
    if not int(layer) in in_db_connection.keys():
        grass.fatal('No attribute table connected vector map {} at \
                    layer {}.'.format(patches, layer))

    #Check if cat column exists
    pcols = grass.vector.vector_columns(patch_map, layer=layer)

    #Check if cat column exists
    if not 'cat' in pcols.keys():
        grass.fatal('Cannot find the reqired column cat in vector map \
                    {}.'.format(patches))

    #Check if pop_proxy column exists
    if not pop_proxy in pcols.keys():
        grass.fatal('Cannot find column {} in vector map \
                    {}'.format(pop_proxy, patches))

    #Check if pop_proxy column is numeric type
    if not pcols[pop_proxy]['type'] in ['INTEGER', 'REAL', 'DOUBLE PRECISION']:
        grass.fatal('Column {} is of type {}. Only numeric types \
                    (integer or double precision) \
                    allowed!'.format(pop_proxy, pcols[pop_proxy]['type']))

    #Check if pop_proxy column does not contain values <= 0
    pop_vals = np.fromstring(grass.read_command('v.db.select',
                                                flags='c',
                                                map=patches,
                                                columns=pop_proxy,
                                                nv=-9999).rstrip('\n'),
                             dtype=float,
                             sep='\n')

    if np.min(pop_vals) <= 0:
        grass.fatal('Column {} contains values <= 0 or NULL. Neither \
                    values <= 0 nor NULL allowed!}'.format(pop_proxy))

    ##############################################
    # Use pygrass region instead of grass.parse_command !?!
    start_reg = grass.parse_command('g.region', flags='ugp')

    max_n = start_reg['n']
    min_s = start_reg['s']
    max_e = start_reg['e']
    min_w = start_reg['w']
    # cost_nsres = reg['nsres']
    # cost_ewres = reg['ewres']

    # Rasterize patches
    # http://www.gdal.org/gdal_tutorial.html
    # http://geoinformaticstutorial.blogspot.no/2012/11/convert-
    # shapefile-to-raster-with-gdal.html
    if t_flag:
        # Rasterize patches with "all-touched" mode using GDAL
        # Read region-settings (not needed canuse max_n, min_s, max_e,
        # min_w nsres, ewres...
        prast = os.path.join(folder, 'patches_rast.tif')

        # Check if GDAL-GRASS plugin is installed
        if ogr.GetDriverByName('GRASS'):
            #With GDAL-GRASS plugin
            #Locate file for patch vector map
            pfile = grass.parse_command('g.findfile',
                                        element='vector',
                                        file=patches,
                                        mapset=patches_mapset)['file']
            pfile = os.path.join(pfile, 'head')

        else:
            # Without GDAL-GRASS-plugin
            grass.warning("Cannot find GDAL-GRASS plugin. Consider \
                          installing it in order to save time for \
                          all-touched rasterisation")
            pfile = os.path.join(folder, 'patches_vect.gpkg')
            # Export patch vector map to temp-file in a GDAL-readable
            # format (shp)
            grass.run_command('v.out.ogr',
                              flags='m',
                              quiet=True,
                              input=patch_map,
                              type='area',
                              layer=layer,
                              output=pfile,
                              lco='GEOMETRY_NAME=geom')

        # Rasterize vector map with all-touched option
        os.system('gdal_rasterize -l {} -at -tr {} {} \
                  -te {} {} {} {} -ot Uint32 -a cat \
                  {} {} -q'.format(patches, start_reg['ewres'],
                                   start_reg['nsres'], start_reg['w'],
                                   start_reg['s'], start_reg['e'],
                                   start_reg['n'], pfile, prast))

        if not ogr.GetDriverByName('GRASS'):
            # Remove vector temp-file
            os.remove(os.path.join(folder, 'patches_vect.gpkg'))

        # Import rasterized patches
        grass.run_command('r.external',
                          flags='o',
                          quiet=True,
                          input=prast,
                          output='{}_patches_pol'.format(TMP_PREFIX))

    else:
        # Simple rasterisation (only area)
        # in G 7.6 also with support for 'centroid'
        if float(grass.version()['version'][:3]) >= 7.6:
            conv_types = ['area', 'centroid']
        else:
            conv_types = ['area']
        grass.run_command('v.to.rast',
                          quiet=True,
                          input=patches,
                          use='cat',
                          type=conv_types,
                          output='{}_patches_pol'.format(TMP_PREFIX))

    # Extract boundaries from patch raster map
    grass.run_command('r.mapcalc',
                      expression='{p}_patches_boundary=if(\
    {p}_patches_pol,\
    if((\
    (isnull({p}_patches_pol[-1,0])||| \
    {p}_patches_pol[-1,0]!={p}_patches_pol)||| \
    (isnull({p}_patches_pol[0,1])||| \
    {p}_patches_pol[0,1]!={p}_patches_pol)||| \
    (isnull({p}_patches_pol[1,0])||| \
    {p}_patches_pol[1,0]!={p}_patches_pol)||| \
    (isnull({p}_patches_pol[0,-1])||| \
    {p}_patches_pol[0,-1]!={p}_patches_pol)), \
    {p}_patches_pol,null()), null())'.format(p=TMP_PREFIX),
                      quiet=True)

    rasterized_cats = grass.read_command(
        'r.category',
        separator='newline',
        map='{p}_patches_boundary'.format(p=TMP_PREFIX)).replace(
            '\t', '').strip('\n')
    rasterized_cats = list(
        map(int, set([x for x in rasterized_cats.split('\n') if x != ''])))

    #Init output vector maps if they are requested by user
    network = VectorTopo(edge_map)
    network_columns = [(u'cat', 'INTEGER PRIMARY KEY'), (u'from_p', 'INTEGER'),
                       (u'to_p', 'INTEGER'), (u'min_dist', 'DOUBLE PRECISION'),
                       (u'dist', 'DOUBLE PRECISION'),
                       (u'max_dist', 'DOUBLE PRECISION')]
    network.open('w', tab_name=edge_map, tab_cols=network_columns)

    vertex = VectorTopo(vertex_map)
    vertex_columns = [
        (u'cat', 'INTEGER PRIMARY KEY'),
        (pop_proxy, 'DOUBLE PRECISION'),
    ]
    vertex.open('w', tab_name=vertex_map, tab_cols=vertex_columns)

    if p_flag:
        # Init cost paths file for start-patch
        grass.run_command('v.edit',
                          quiet=True,
                          map=shortest_paths,
                          tool='create')
        grass.run_command('v.db.addtable',
                          quiet=True,
                          map=shortest_paths,
                          columns="cat integer,\
                                   from_p integer,\
                                   to_p integer,\
                                   dist_min double precision,\
                                   dist double precision,\
                                   dist_max double precision")

    start_region_bbox = Bbox(north=float(max_n),
                             south=float(min_s),
                             east=float(max_e),
                             west=float(min_w))
    vpatches = VectorTopo(patches, mapset=patches_mapset)
    vpatches.open('r', layer=int(layer))

    ###Loop through patches
    vpatch_ids = np.array(vpatches.features_to_wkb_list(
        feature_type="centroid", bbox=start_region_bbox),
                          dtype=[('vid', 'uint32'), ('cat', 'uint32'),
                                 ('geom', '|S10')])
    cats = set(vpatch_ids['cat'])
    n_cats = len(cats)
    if n_cats < len(vpatch_ids['cat']):
        grass.verbose('At least one MultiPolygon found in patch map.\n \
                      Using average coordinates of the centroids for \
                      visual representation of the patch.')

    for cat in cats:
        if cat not in rasterized_cats:
            grass.warning('Patch {} has not been rasterized and will \
                          therefore not be treated as part of the \
                          network. Consider using t-flag or change \
                          resolution.'.format(cat))

            continue
        grass.verbose("Calculating connectivity-distances for patch \
                      number {}".format(cat))

        # Filter
        from_vpatch = vpatch_ids[vpatch_ids['cat'] == cat]

        # Get patch ID
        if from_vpatch['vid'].size == 1:
            from_centroid = Centroid(v_id=int(from_vpatch['vid']),
                                     c_mapinfo=vpatches.c_mapinfo)
            from_x = from_centroid.x
            from_y = from_centroid.y

            # Get centroid
            if not from_centroid:
                continue
        else:
            xcoords = []
            ycoords = []
            for f_p in from_vpatch['vid']:
                from_centroid = Centroid(v_id=int(f_p),
                                         c_mapinfo=vpatches.c_mapinfo)
                xcoords.append(from_centroid.x)
                ycoords.append(from_centroid.y)

                # Get centroid
                if not from_centroid:
                    continue
            from_x = np.average(xcoords)
            from_y = np.average(ycoords)

        # Get BoundingBox
        from_bbox = grass.parse_command('v.db.select',
                                        map=patch_map,
                                        flags='r',
                                        where='cat={}'.format(cat))

        attr_filter = vpatches.table.filters.select(pop_proxy)
        attr_filter = attr_filter.where("cat={}".format(cat))
        proxy_val = vpatches.table.execute().fetchone()

        # Prepare start patch
        start_patch = '{}_patch_{}'.format(TMP_PREFIX, cat)
        reclass_rule = grass.encode('{} = 1\n* = NULL'.format(cat))
        recl = grass.feed_command(
            'r.reclass',
            quiet=True,
            input='{}_patches_boundary'.format(TMP_PREFIX),
            output=start_patch,
            rules='-')
        recl.stdin.write(reclass_rule)
        recl.stdin.close()
        recl.wait()

        # Check if patch was rasterised (patches smaller raster resolution and close to larger patches may not be rasterised)
        #start_check = grass.parse_command('r.info', flags='r', map=start_patch)
        #start_check = grass.parse_command('r.univar', flags='g', map=start_patch)
        #print(start_check)
        """if start_check['min'] != '1':
            grass.warning('Patch {} has not been rasterized and will \
                          therefore not be treated as part of the \
                          network. Consider using t-flag or change \
                          resolution.'.format(cat))

            grass.run_command('g.remove', flags='f', vector=start_patch,
                              raster=start_patch, quiet=True)
            grass.del_temp_region()
            continue"""

        # Prepare stop patches
        ############################################
        reg = grass.parse_command('g.region',
                                  flags='ug',
                                  quiet=True,
                                  raster=start_patch,
                                  n=float(from_bbox['n']) + float(cutoff),
                                  s=float(from_bbox['s']) - float(cutoff),
                                  e=float(from_bbox['e']) + float(cutoff),
                                  w=float(from_bbox['w']) - float(cutoff),
                                  align='{}_patches_pol'.format(TMP_PREFIX))

        north = reg['n'] if max_n > reg['n'] else max_n
        south = reg['s'] if min_s < reg['s'] else min_s
        east = reg['e'] if max_e < reg['e'] else max_e
        west = reg['w'] if min_w > reg['w'] else min_w

        # Set region to patch search radius
        grass.use_temp_region()
        grass.run_command('g.region',
                          quiet=True,
                          n=north,
                          s=south,
                          e=east,
                          w=west,
                          align='{}_patches_pol'.format(TMP_PREFIX))

        # Create buffer around start-patch as a mask
        # for cost distance analysis
        grass.run_command('r.buffer',
                          quiet=True,
                          input=start_patch,
                          output='MASK',
                          distances=cutoff)
        grass.run_command('r.mapcalc',
                          quiet=True,
                          expression='{pf}_patch_{p}_neighbours_contur=\
                                     if({pf}_patches_boundary=={p},\
                                     null(),\
                                     {pf}_patches_boundary)'.format(
                              pf=TMP_PREFIX, p=cat))
        grass.run_command('r.mask', flags='r', quiet=True)

        # Calculate cost distance
        cost_distance_map = '{}_patch_{}_cost_dist'.format(prefix, cat)
        grass.run_command('r.cost',
                          flags=dist_flags,
                          quiet=True,
                          overwrite=True,
                          input=costs,
                          output=cost_distance_map,
                          start_rast=start_patch,
                          memory=memory)

        #grass.run_command('g.region', flags='up')
        # grass.raster.raster_history(cost_distance_map)
        cdhist = History(cost_distance_map)
        cdhist.clear()
        cdhist.creator = os.environ['USER']
        cdhist.write()
        # History object cannot modify description
        grass.run_command('r.support',
                          map=cost_distance_map,
                          description='Generated by r.connectivity.distance',
                          history=os.environ['CMDLINE'])

        # Export distance at boundaries
        maps = '{0}_patch_{1}_neighbours_contur,{2}_patch_{1}_cost_dist'
        maps = maps.format(TMP_PREFIX, cat, prefix),

        connections = grass.encode(
            grass.read_command('r.stats',
                               flags='1ng',
                               quiet=True,
                               input=maps,
                               separator=';').rstrip('\n'))
        if connections:
            con_array = np.genfromtxt(BytesIO(connections),
                                      delimiter=';',
                                      dtype=None,
                                      names=['x', 'y', 'cat', 'dist'])
        else:
            grass.warning('No connections for patch {}'.format(cat))

            # Write centroid to vertex map
            vertex.write(Point(from_x, from_y), cat=int(cat), attrs=proxy_val)
            vertex.table.conn.commit()

            # Remove temporary map data
            grass.run_command('g.remove',
                              quiet=True,
                              flags='f',
                              type=['raster', 'vector'],
                              pattern="{}*{}*".format(TMP_PREFIX, cat))
            grass.del_temp_region()
            continue

        #Find closest points on neigbour patches
        to_cats = set(np.atleast_1d(con_array['cat']))
        to_coords = []
        for to_cat in to_cats:
            connection = con_array[con_array['cat'] == to_cat]
            connection.sort(order=['dist'])
            pixel = border_dist if len(
                connection) > border_dist else len(connection) - 1
            # closest_points_x = connection['x'][pixel]
            # closest_points_y = connection['y'][pixel]
            closest_points_to_cat = to_cat
            closest_points_min_dist = connection['dist'][0]
            closest_points_dist = connection['dist'][pixel]
            closest_points_max_dist = connection['dist'][-1]
            to_patch_ids = vpatch_ids[vpatch_ids['cat'] == int(to_cat)]['vid']

            if len(to_patch_ids) == 1:
                to_centroid = Centroid(v_id=to_patch_ids,
                                       c_mapinfo=vpatches.c_mapinfo)
                to_x = to_centroid.x
                to_y = to_centroid.y
            elif len(to_patch_ids) >= 1:
                xcoords = []
                ycoords = []
                for t_p in to_patch_ids:
                    to_centroid = Centroid(v_id=int(t_p),
                                           c_mapinfo=vpatches.c_mapinfo)
                    xcoords.append(to_centroid.x)
                    ycoords.append(to_centroid.y)

                    # Get centroid
                    if not to_centroid:
                        continue
                to_x = np.average(xcoords)
                to_y = np.average(ycoords)

            to_coords.append('{},{},{},{},{},{}'.format(
                connection['x'][0], connection['y'][0], to_cat,
                closest_points_min_dist, closest_points_dist,
                closest_points_max_dist))

            #Save edges to network dataset
            if closest_points_dist <= 0:
                zero_dist = 1

            # Write data to network
            network.write(Line([(from_x, from_y), (to_x, to_y)]),
                          cat=lin_cat,
                          attrs=(
                              cat,
                              int(closest_points_to_cat),
                              closest_points_min_dist,
                              closest_points_dist,
                              closest_points_max_dist,
                          ))
            network.table.conn.commit()

            lin_cat = lin_cat + 1

        # Save closest points and shortest paths through cost raster as
        # vector map (r.drain limited to 1024 points) if requested
        if p_flag:
            grass.verbose('Extracting shortest paths for patch number \
                          {}...'.format(cat))

            points_n = len(to_cats)

            tiles = int(points_n / 1024.0)
            rest = points_n % 1024
            if not rest == 0:
                tiles = tiles + 1

            tile_n = 0
            while tile_n < tiles:
                tile_n = tile_n + 1
                #Import closest points for start-patch in 1000er blocks
                sp = grass.feed_command('v.in.ascii',
                                        flags='nr',
                                        overwrite=True,
                                        quiet=True,
                                        input='-',
                                        stderr=subprocess.PIPE,
                                        output="{}_{}_cp".format(
                                            TMP_PREFIX, cat),
                                        separator=",",
                                        columns="x double precision,\
                                           y double precision,\
                                           to_p integer,\
                                           dist_min double precision,\
                                           dist double precision,\
                                           dist_max double precision")
                sp.stdin.write(grass.encode("\n".join(to_coords)))
                sp.stdin.close()
                sp.wait()

                # Extract shortest paths for start-patch in chunks of
                # 1024 points
                cost_paths = "{}_{}_cost_paths".format(TMP_PREFIX, cat)
                start_points = "{}_{}_cp".format(TMP_PREFIX, cat)
                grass.run_command('r.drain',
                                  overwrite=True,
                                  quiet=True,
                                  input=cost_distance_map,
                                  output=cost_paths,
                                  drain=cost_paths,
                                  start_points=start_points)

                grass.run_command('v.db.addtable',
                                  map=cost_paths,
                                  quiet=True,
                                  columns="cat integer,\
                                   from_p integer,\
                                   to_p integer,\
                                   dist_min double precision,\
                                   dist double precision,\
                                   dist_max double precision")
                grass.run_command('v.db.update',
                                  map=cost_paths,
                                  column='from_p',
                                  value=cat,
                                  quiet=True)
                grass.run_command('v.distance',
                                  quiet=True,
                                  from_=cost_paths,
                                  to=start_points,
                                  upload='to_attr',
                                  column='to_p',
                                  to_column='to_p')
                grass.run_command('v.db.join',
                                  quiet=True,
                                  map=cost_paths,
                                  column='to_p',
                                  other_column='to_p',
                                  other_table=start_points,
                                  subset_columns='dist_min,dist,dist_max')

                #grass.run_command('v.info', flags='c',
                #                  map=cost_paths)
                grass.run_command('v.patch',
                                  flags='ae',
                                  overwrite=True,
                                  quiet=True,
                                  input=cost_paths,
                                  output=shortest_paths)

                # Remove temporary map data
                grass.run_command('g.remove',
                                  quiet=True,
                                  flags='f',
                                  type=['raster', 'vector'],
                                  pattern="{}*{}*".format(TMP_PREFIX, cat))

        # Remove temporary map data for patch
        if r_flag:
            grass.run_command('g.remove',
                              flags='f',
                              type='raster',
                              name=cost_distance_map,
                              quiet=True)

        vertex.write(Point(from_x, from_y), cat=int(cat), attrs=proxy_val)

        vertex.table.conn.commit()

        # Print progress message
        grass.percent(i=int((float(counter) / n_cats) * 100), n=100, s=3)

        # Update counter for progress message
        counter = counter + 1

    if zero_dist:
        grass.warning('Some patches are directly adjacent to others. \
                       Minimum distance set to 0.0000000001')

    # Close vector maps and build topology
    network.close()
    vertex.close()

    # Add vertex attributes
    # grass.run_command('v.db.addtable', map=vertex_map)
    # grass.run_command('v.db.join', map=vertex_map, column='cat',
    #                   other_table=in_db_connection[int(layer)]['table'],
    #                   other_column='cat', subset_columns=pop_proxy,
    #                   quiet=True)

    # Add history and meta data to produced maps
    grass.run_command('v.support',
                      flags='h',
                      map=edge_map,
                      person=os.environ['USER'],
                      cmdhist=os.environ['CMDLINE'])

    grass.run_command('v.support',
                      flags='h',
                      map=vertex_map,
                      person=os.environ['USER'],
                      cmdhist=os.environ['CMDLINE'])

    if p_flag:
        grass.run_command('v.support',
                          flags='h',
                          map=shortest_paths,
                          person=os.environ['USER'],
                          cmdhist=os.environ['CMDLINE'])

    # Output also Conefor files if requested
    if conefor_dir:
        query = """SELECT p_from, p_to, avg(dist) FROM
                 (SELECT
                 CASE
                 WHEN from_p > to_p THEN to_p
                 ELSE from_p END AS p_from,
                    CASE
                 WHEN from_p > to_p THEN from_p
                 ELSE to_p END AS p_to,
                 dist
                 FROM {}) AS x
                 GROUP BY p_from, p_to""".format(edge_map)
        with open(os.path.join(conefor_dir, 'undirected_connection_file'),
                  'w') as edges:
            edges.write(
                grass.read_command('db.select', sql=query, separator=' '))
        with open(os.path.join(conefor_dir, 'directed_connection_file'),
                  'w') as edges:
            edges.write(
                grass.read_command('v.db.select',
                                   map=edge_map,
                                   separator=' ',
                                   flags='c'))
        with open(os.path.join(conefor_dir, 'node_file'), 'w') as nodes:
            nodes.write(
                grass.read_command('v.db.select',
                                   map=vertex_map,
                                   separator=' ',
                                   flags='c'))
Beispiel #19
0
def main():
    global temp_dist, temp_src

    input = options['input']
    output = options['output']
    distances = options['distances']
    units = options['units']
    zero = flags['z']

    tmp = str(os.getpid())
    temp_dist = "r.buffer.tmp.%s.dist" % tmp
    temp_src = "r.buffer.tmp.%s.src" % tmp

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

    scale = scales[units]

    distances = distances.split(',')
    distances1 = [scale * float(d) for d in distances]
    distances2 = [d * d for d in distances1]

    s = grass.read_command("g.proj", flags='j')
    kv = grass.parse_key_val(s)
    if kv['+proj'] == 'longlat':
        metric = 'geodesic'
    else:
        metric = 'squared'

    grass.run_command('r.grow.distance',
                      input=input,
                      metric=metric,
                      distance=temp_dist,
                      flags='m')

    if zero:
        exp = "$temp_src = if($input == 0,null(),1)"
    else:
        exp = "$temp_src = if(isnull($input),null(),1)"

    grass.message(_("Extracting buffers (1/2)..."))
    grass.mapcalc(exp, temp_src=temp_src, input=input)

    exp = "$output = if(!isnull($input),$input,%s)"
    if metric == 'squared':
        for n, dist2 in enumerate(distances2):
            exp %= "if($dist <= %f,%d,%%s)" % (dist2, n + 2)
    else:
        for n, dist2 in enumerate(distances1):
            exp %= "if($dist <= %f,%d,%%s)" % (dist2, n + 2)
    exp %= "null()"

    grass.message(_("Extracting buffers (2/2)..."))
    grass.mapcalc(exp, output=output, input=temp_src, dist=temp_dist)

    p = grass.feed_command('r.category', map=output, separator=':', rules='-')
    msg = "1:distances calculated from these locations\n"
    p.stdin.write(encode(msg))
    d0 = "0"
    for n, d in enumerate(distances):
        msg = "%d:%s-%s %s\n" % (n + 2, d0, d, units)
        p.stdin.write(encode(msg))
        d0 = d
    p.stdin.close()
    p.wait()

    grass.run_command('r.colors', map=output, color='rainbow')

    # write cmd history:
    grass.raster_history(output)
Beispiel #20
0
def main():
    raster = options["raster"]
    maskcats = options["maskcats"]
    vector = options["vector"]
    layer = options["layer"]
    cats = options["cats"]
    where = options["where"]
    remove = flags["r"]
    invert = flags["i"]

    if not remove and not raster and not vector:
        grass.fatal(
            _("Either parameter <raster> or parameter <vector> is required"))

    mapset = grass.gisenv()["MAPSET"]
    exists = bool(
        grass.find_file("MASK", element="cell", mapset=mapset)["file"])

    if remove:
        # -> remove
        if exists:
            if sys.platform == "win32":
                grass.run_command("g.remove",
                                  flags="if",
                                  quiet=True,
                                  type="raster",
                                  name="MASK")
            else:
                grass.run_command("g.remove",
                                  flags="f",
                                  quiet=True,
                                  type="raster",
                                  name="MASK")
            grass.message(_("Raster MASK removed"))
        else:
            grass.fatal(_("No existing MASK to remove"))
    else:
        # -> create
        if exists:
            if not grass.overwrite():
                grass.fatal(
                    _("MASK already found in current mapset. Delete first or overwrite."
                      ))
            else:
                grass.warning(_("MASK already exists and will be overwritten"))
                grass.run_command("g.remove",
                                  flags="f",
                                  quiet=True,
                                  type="raster",
                                  name="MASK")

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

            if maskcats != "*" and not remove:
                if grass.raster_info(raster)["datatype"] != "CELL":
                    grass.fatal(
                        _("The raster map <%s> must be integer (CELL type) "
                          " in order to use the 'maskcats' parameter") %
                        raster)

            p = grass.feed_command("r.reclass",
                                   input=raster,
                                   output="MASK",
                                   overwrite=True,
                                   rules="-")
            res = "%s = 1" % maskcats
            p.stdin.write(encode(res))
            p.stdin.close()
            p.wait()
        elif vector:
            vector_name = grass.find_file(vector, "vector")["fullname"]
            if not vector_name:
                grass.fatal(_("Vector map <%s> not found") % vector)

            # parser bug?
            if len(cats) == 0:
                cats = None
            if len(where) == 0:
                where = None

            if grass.vector_info_topo(vector_name)["areas"] < 1:
                grass.warning(
                    _("No area found in vector map <%s>. "
                      "Creating a convex hull for MASK.") % vector_name)
                global tmp_hull
                tmp_hull = "tmp_hull_%d" % os.getpid()
                to_rast_input = tmp_hull
                # force 'flat' convex hull for 3D vector maps
                try:
                    grass.run_command(
                        "v.hull",
                        flags="f",
                        quiet=True,
                        input=vector_name,
                        output=tmp_hull,
                        layer=layer,
                        cats=cats,
                        where=where,
                    )
                except CalledModuleError:
                    grass.fatal(
                        _("Unable to create a convex hull for vector map <%s>")
                        % vector_name)
            else:
                to_rast_input = vector_name

            env = os.environ.copy()
            if grass.verbosity() > 1:
                env["GRASS_VERBOSE"] = "1"
            grass.run_command(
                "v.to.rast",
                input=to_rast_input,
                layer=layer,
                output="MASK",
                use="val",
                val="1",
                type="area",
                cats=cats,
                where=where,
                env=env,
            )

        if invert:
            global tmp
            tmp = "r_mask_%d" % os.getpid()
            grass.run_command("g.rename", raster=("MASK", tmp), quiet=True)
            grass.message(_("Creating inverted raster MASK..."))
            grass.mapcalc("MASK = if(isnull($tmp), 1, null())", tmp=tmp)
            grass.verbose(_("Inverted raster MASK created"))
        else:
            grass.verbose(_("Raster MASK created"))

        grass.message(
            _("All subsequent raster operations will be limited to "
              "the MASK area. Removing or renaming raster map named "
              "'MASK' will restore raster operations to normal."))
def main():
    input = options['input']
    output = options['output']
    altitude = options['altitude']
    azimuth = options['azimuth']
    zmult = options['zmult']
    scale = float(options['scale'])
    units = options['units']
    verbose_level = os.getenv('GRASS_VERBOSE')
    if verbose_level is None:
        verbose_level = 2
    
    if not grass.find_file(input)['file']:
	grass.fatal(_("Raster map <%s> not found") % input)

    if input == output:
	grass.fatal(_("Input elevation map and output relief map must have different names"))
    
    # LatLong locations only:
    if units == 'meters':
        # scale=111120
	scale *= 1852 * 60

    # LatLong locations only:
    if units == 'feet':
        # scale=364567.2
	scale *= 6076.12 * 60

    #correct azimuth to East (GRASS convention):
    #  this seems to be backwards, but in fact it works so leave it.
    az = float(azimuth) - 90

    t = string.Template(
	r'''eval( \
	x=($zmult*$input[-1,-1] + 2*$zmult*$input[0,-1] + $zmult*$input[1,-1] - \
	$zmult*$input[-1,1] - 2*$zmult*$input[0,1] - $zmult*$input[1,1])/(8.*ewres()*$scale), \
	y=($zmult*$input[-1,-1] + 2*$zmult*$input[-1,0] + $zmult*$input[-1,1] - \
	$zmult*$input[1,-1] - 2*$zmult*$input[1,0] - $zmult*$input[1,1])/(8.*nsres()*$scale), \
	slope=90.-atan(sqrt(x*x + y*y)), \
	a=round(atan(x,y)), \
	a=if(isnull(a),1,a), \
	aspect=if(x!=0||y!=0,if(a,a,360.)), \
	cang = sin($altitude)*sin(slope) + cos($altitude)*cos(slope) * cos($az-aspect) \
	)
	$output = if(isnull(cang), null(), 100.*cang)''')
    expr = t.substitute(altitude = altitude, az = az, input = input, output = output, scale = scale, zmult = zmult)
    p = grass.feed_command('r.mapcalc')
    p.stdin.write(expr)
    p.stdin.close()

    if p.wait() != 0:
	grass.fatal(_("In calculation, script aborted."))

    if verbose_level < 3:
        grass.run_command('r.colors', map = output, color = 'grey', quiet = True)
    else:
        grass.run_command('r.colors', map = output, color = 'grey')
    
    # record metadata
    grass.run_command('r.support', map = output, title = 'Shaded relief of "%s"' % input, history = '')
    grass.run_command('r.support', map = output, history = "r.shaded.relief settings:")
    t = string.Template("altitude=$altitude  azimuth=$azimuth zmult=$zmult  scale=$scale")
    parms = dict(altitude = altitude, azimuth = azimuth, zmult = zmult, scale = options['scale'])
    grass.run_command('r.support', map = output, history = t.substitute(parms))
    if units:
	grass.run_command('r.support', map = output, history = "  units=%s (adjusted scale=%s)" % (units, scale))

    # write cmd history:
    grass.raster_history(output)
Beispiel #22
0
def main():
    raster = options['raster']
    maskcats = options['maskcats']
    vector = options['vector']
    layer = options['layer']
    cats = options['cats']
    where = options['where']
    remove = flags['r']
    invert = flags['i']

    if not remove and not raster and not vector:
        grass.fatal(_("Either parameter <raster> ot parameter <vector> is required"))

    mapset = grass.gisenv()['MAPSET']
    exists = bool(grass.find_file('MASK', element='cell', mapset=mapset)['file'])

    if remove:
        # -> remove
        if exists:
            if sys.platform == 'win32':
                grass.run_command('g.remove', flags='if', quiet=True,
                                  type='raster', name='MASK')
            else:
                grass.run_command('g.remove', flags='f', quiet=True,
                                  type='raster', name='MASK')
            grass.message(_("Raster MASK removed"))
        else:
            grass.fatal(_("No existing MASK to remove"))
    else:
        # -> create
        if exists:
            if not grass.overwrite():
                grass.fatal(_("MASK already found in current mapset. Delete first or overwrite."))
            else:
                grass.warning(_("MASK already exists and will be overwritten"))
                grass.run_command('g.remove', flags='f', quiet=True,
                                  type='raster', name='MASK')

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

            if maskcats != '*' and not remove:
                if grass.raster_info(raster)['datatype'] != "CELL":
                    grass.fatal(_("The raster map <%s> must be integer (CELL type) "
                                  " in order to use the 'maskcats' parameter") % raster)

            p = grass.feed_command(
                'r.reclass',
                input=raster,
                output='MASK',
                overwrite=True,
                rules='-')
            p.stdin.write("%s = 1" % maskcats)
            p.stdin.close()
            p.wait()
        elif vector:
            vector_name = grass.find_file(vector, 'vector')['fullname']
            if not vector_name:
                grass.fatal(_("Vector map <%s> not found") % vector)

            # parser bug?
            if len(cats) == 0:
                cats = None
            if len(where) == 0:
                where = None

            if grass.vector_info_topo(vector_name)['areas'] < 1:
                grass.warning(_("No area found in vector map <%s>. "
                                "Creating a convex hull for MASK.") % vector_name)
                global tmp_hull
                tmp_hull = "tmp_hull_%d" % os.getpid()
                to_rast_input = tmp_hull
                # force 'flat' convex hull for 3D vector maps
                try:
                    grass.run_command('v.hull', flags='f', quiet=True,
                                      input=vector_name, output=tmp_hull,
                                      layer=layer, cats=cats, where=where)
                except CalledModuleError:
                    grass.fatal(
                        _("Unable to create a convex hull for vector map <%s>") %
                        vector_name)
            else:
                to_rast_input = vector_name

            env = os.environ.copy()
            if grass.verbosity() > 1:
                env['GRASS_VERBOSE'] = '1'
            grass.run_command('v.to.rast', input=to_rast_input, layer=layer,
                              output='MASK', use='val', val='1',
                              type='area', cats=cats, where=where, env=env)

        if invert:
            global tmp
            tmp = "r_mask_%d" % os.getpid()
            grass.run_command('g.rename', raster=('MASK', tmp), quiet=True)
            grass.message(_("Creating inverted raster MASK..."))
            grass.mapcalc("MASK = if(isnull($tmp), 1, null())", tmp=tmp)
            grass.verbose(_("Inverted raster MASK created"))
        else:
            grass.verbose(_("Raster MASK created"))

        grass.message(_("All subsequent raster operations will be limited to "
                        "the MASK area. Removing or renaming raster map named "
                        "'MASK' will restore raster operations to normal."))
Beispiel #23
0
def main():
    infile = options['input']
    lesser = options['lesser']
    greater = options['greater']
    outfile = options['output']

    s = grass.read_command("g.region", flags = 'p')
    kv = grass.parse_key_val(s, sep = ':')
    s = kv['projection'].strip().split()
    if s == '0':
	grass.fatal(_("xy-locations are not supported"))
	grass.fatal(_("Need projected data with grids in meters"))

    if not lesser and not greater:
	grass.fatal(_("You have to specify either lesser= or greater="))
    if lesser and greater:
	grass.fatal(_("lesser= and greater= are mutually exclusive"))
    if lesser:
	limit = float(lesser)
    if greater:
	limit = float(greater)

    if not grass.find_file(infile)['name']:
	grass.fatal(_("Raster map <%s> not found") % infile)

    clumpfile = "%s.clump.%s" % (infile.split('@')[0], outfile)

    if not grass.overwrite():
	if grass.find_file(clumpfile)['name']:
	    grass.fatal(_("Temporary raster map <%s> exists") % clumpfile)

    grass.message(_("Generating a clumped raster file ..."))
    grass.run_command('r.clump', input = infile, output = clumpfile)

    if lesser:
	grass.message(_("Generating a reclass map with area size less than or equal to %f hectares...") % limit)
    else:
	grass.message(_("Generating a reclass map with area size greater than or equal to %f hectares...") % limit)

    recfile = outfile + '.recl'

    p1 = grass.pipe_command('r.stats', flags = 'aln', input = (clumpfile, infile), fs = '|')
    p2 = grass.feed_command('r.reclass', input = clumpfile, output = recfile, rules = '-')
    for line in p1.stdout:
	f = line.rstrip('\r\n').split('|')
	if len(f) < 5:
	    continue
	hectares = float(f[4]) * 0.0001
	if lesser:
	    test = hectares <= limit
	else:
	    test = hectares >= limit
	if test:
	    p2.stdin.write("%s = %s %s\n" % (f[0], f[2], f[3]))
    p1.wait()
    p2.stdin.close()
    p2.wait()

    grass.message(_("Generating output raster map <%s>...") % outfile)

    grass.mapcalc("$outfile = $recfile", outfile = outfile, recfile = recfile)
    grass.run_command('g.remove', rast = [recfile, clumpfile], quiet = True)
Beispiel #24
0
def main():
    options, flags = grass.parser()
    xAmap = options['xaraster']
    xBmap = options['xbraster']
    yAmap = options['yaraster']
    yBmap = options['ybraster']
    output_basename = options['output']
    custom_threshold = options['custom_threshold']
    stat_threshold = options['stat_threshold']
    Xdelta_name = 'deltaX'
    Ydelta_name = 'deltaY'
    anglemap_name = output_basename + '_angle'
    anglemap_class = anglemap_name + '_class'
    magnitudemap_name = output_basename + '_magnitude'
    changemap_name = output_basename + '_change'

    # Checking that the input maps exist
    if not grass.find_file(name=xAmap, element='cell')['file']:
        grass.fatal("xaraster map <%s> not found" % xAmap)
    if not grass.find_file(name=xBmap, element='cell')['file']:
        grass.fatal("xbraster map <%s> not found" % xBmap)
    if not grass.find_file(name=yAmap, element='cell')['file']:
        grass.fatal("yaraster map <%s> not found" % yAmap)
    if not grass.find_file(name=xBmap, element='cell')['file']:
        grass.fatal("ybraster map <%s> not found" % yBmap)

    TMPRAST.append(Xdelta_name)
    TMPRAST.append(Ydelta_name)

    # Calculating delta for X and Y bands
    grass.message(_("Calculating DeltaX and DeltaY"))
    delta_calculation(Xdelta_name, xBmap, xAmap)
    delta_calculation(Ydelta_name, yBmap, yAmap)

    #Calculating angle and magnitude maps
    grass.message(_("Writing angle map %s") % anglemap_name)
    angle_calculation(anglemap_name, Xdelta_name, Ydelta_name)

    grass.message(_("Writing magnitude map %s") % magnitudemap_name)
    magnitude_calculation(magnitudemap_name, Xdelta_name, Ydelta_name)

    # Reclassifing angle map to get a map with the four quadrants
    keys = ['1', '2', '3', '4']
    vals = [0, 90, 180, 270, 360]
    rvals = [(int(vals[i - 1]), int(vals[i]), keys[i - 1], vals[i - 1],
              vals[i]) for i in range(1, len(vals))]
    rules = '\n'.join(['%3d thru %3d = %s   %s-%s' % v for v in rvals])
    script.write_command('r.reclass',
                         input=anglemap_name,
                         output=anglemap_class,
                         rules='-',
                         overwrite=True,
                         stdin=rules.encode())

    # Generating the change detection map using the given threshold
    if custom_threshold:
        threshold = custom_threshold
        grass.message(_("Threshold is %s") % threshold)
        grass.message(_("Writing change detection map %s") % changemap_name)
        # Creating the final map of the change, using a custom threshold
        change_map_calculation(changemap_name, magnitudemap_name, threshold,
                               anglemap_class)
    elif stat_threshold:
        #Getting values of mean and standard dev of magnitude to calculate the change detection criteria (> mean + N*stdev)
        univar = grass.read_command('r.univar',
                                    map=magnitudemap_name,
                                    flags='g')

        found = 0
        for line in univar.splitlines():
            name, val = line.split('=')
            if name == 'mean':
                grass.message(_("Mean of magnitude values is: %s") % val)
                mean = val
                found += 1
            if name == 'stddev':
                grass.message(
                    _("Standard deviation of magnitude values is: %s") % val)
                stddev = val
                found += 1
        if found != 2:
            grass.fatal("Couldn\'t find mean or stddev!")

        adding_value = float(stat_threshold) * float(stddev)
        threshold = float(mean) + float(adding_value)
        grass.message(_("Threshold is %s") % threshold)
        #Creating the final map of the change, using a statistical threshold
        change_map_calculation(changemap_name, magnitudemap_name, threshold,
                               anglemap_class)
    else:
        grass.message(
            _("No threshold given, only angle and magnitude maps have been created"
              ))

    # anglemap_class: set colors
    iva_colors = '1 217 255 0\n2 10 214 10\n3 75 173 255\n4 139 105 20\nnv 255 255 255\ndefault 255 255 255'
    p = grass.feed_command('r.colors', map=anglemap_class, rules='-')
    p.stdin.write(iva_colors.encode())
    p.stdin.close()

    # anglemap_class: set categories
    rules = [
        '1:moisture reduction', '2:chlorophyll increase',
        '3:moisture increase', '4:bare soil increase'
    ]
    p = grass.feed_command('r.category',
                           map=anglemap_class,
                           rules='-',
                           separator=':')
    p.stdin.write(('\n'.join(rules)).encode())
    p.stdin.close()

    return 0
Beispiel #25
0
def reclass(inf, outf, lim, clump, diag, les):
    infile = inf
    outfile = outf
    lesser = les
    limit = lim
    clumped = clump
    diagonal = diag

    s = grass.read_command("g.region", flags='p')
    kv = grass.parse_key_val(s, sep=':')
    s = kv['projection'].strip().split()
    if s == '0':
        grass.fatal(_("xy-locations are not supported"))
        grass.fatal(_("Need projected data with grids in meters"))

    if not grass.find_file(infile)['name']:
        grass.fatal(_("Raster map <%s> not found") % infile)

    if clumped and diagonal:
        grass.fatal(_("flags c and d are mutually exclusive"))

    if clumped:
        clumpfile = infile
    else:
        clumpfile = "%s.clump.%s" % (infile.split('@')[0], outfile)
        TMPRAST.append(clumpfile)

        if not grass.overwrite():
            if grass.find_file(clumpfile)['name']:
                grass.fatal(_("Temporary raster map <%s> exists") % clumpfile)
        if diagonal:
            grass.message(_("Generating a clumped raster file including "
                            "diagonal neighbors..."))
            grass.run_command('r.clump', flags='d', input=infile,
                              output=clumpfile)
        else:
            grass.message(_("Generating a clumped raster file ..."))
            grass.run_command('r.clump', input=infile, output=clumpfile)

    if lesser:
        grass.message(_("Generating a reclass map with area size less than "
                        "or equal to %f hectares...") % limit)
    else:
        grass.message(_("Generating a reclass map with area size greater "
                        "than or equal to %f hectares...") % limit)

    recfile = outfile + '.recl'
    TMPRAST.append(recfile)

    sflags = 'aln'
    if grass.raster_info(infile)['datatype'] in ('FCELL', 'DCELL'):
        sflags += 'i'
    p1 = grass.pipe_command('r.stats', flags=sflags, input=(clumpfile, infile),
                            sep=';')
    p2 = grass.feed_command('r.reclass', input=clumpfile, output=recfile,
                            rules='-')
    rules = ''
    for line in p1.stdout:
        f = line.rstrip(os.linesep).split(';')
        if len(f) < 5:
            continue
        hectares = float(f[4]) * 0.0001
        if lesser:
            test = hectares <= limit
        else:
            test = hectares >= limit
        if test:
            rules += "%s = %s %s\n" % (f[0], f[2], f[3])
    if rules:
        p2.stdin.write(rules)
    p1.wait()
    p2.stdin.close()
    p2.wait()
    if p2.returncode != 0:
        if lesser:
            grass.fatal(_("No areas of size less than or equal to %f "
                          "hectares found.") % limit)
        else:
            grass.fatal(_("No areas of size greater than or equal to %f "
                          "hectares found.") % limit)
    grass.mapcalc("$outfile = $recfile", outfile=outfile, recfile=recfile)
Beispiel #26
0
def reclass(inf, outf, lim, clump, diag, les):
    infile = inf
    outfile = outf
    lesser = les
    limit = lim
    clumped = clump
    diagonal = diag

    s = grass.read_command("g.region", flags='p')
    s = decode(s)
    kv = grass.parse_key_val(s, sep=':')
    s = kv['projection'].strip().split()
    if s == '0':
        grass.fatal(_("xy-locations are not supported"))
        grass.fatal(_("Need projected data with grids in meters"))

    if not grass.find_file(infile)['name']:
        grass.fatal(_("Raster map <%s> not found") % infile)

    if clumped and diagonal:
        grass.fatal(_("flags c and d are mutually exclusive"))

    if clumped:
        clumpfile = infile
    else:
        clumpfile = "%s.clump.%s" % (infile.split('@')[0], outfile)
        TMPRAST.append(clumpfile)

        if not grass.overwrite():
            if grass.find_file(clumpfile)['name']:
                grass.fatal(_("Temporary raster map <%s> exists") % clumpfile)
        if diagonal:
            grass.message(
                _("Generating a clumped raster file including "
                  "diagonal neighbors..."))
            grass.run_command('r.clump',
                              flags='d',
                              input=infile,
                              output=clumpfile)
        else:
            grass.message(_("Generating a clumped raster file ..."))
            grass.run_command('r.clump', input=infile, output=clumpfile)

    if lesser:
        grass.message(
            _("Generating a reclass map with area size less than "
              "or equal to %f hectares...") % limit)
    else:
        grass.message(
            _("Generating a reclass map with area size greater "
              "than or equal to %f hectares...") % limit)

    recfile = outfile + '.recl'
    TMPRAST.append(recfile)

    sflags = 'aln'
    if grass.raster_info(infile)['datatype'] in ('FCELL', 'DCELL'):
        sflags += 'i'
    p1 = grass.pipe_command('r.stats',
                            flags=sflags,
                            input=(clumpfile, infile),
                            sep=';')
    p2 = grass.feed_command('r.reclass',
                            input=clumpfile,
                            output=recfile,
                            rules='-')
    rules = ''
    for line in p1.stdout:
        f = decode(line).rstrip(os.linesep).split(';')
        if len(f) < 5:
            continue
        hectares = float(f[4]) * 0.0001
        if lesser:
            test = hectares <= limit
        else:
            test = hectares >= limit
        if test:
            rules += "%s = %s %s\n" % (f[0], f[2], f[3])
    if rules:
        p2.stdin.write(encode(rules))
    p1.wait()
    p2.stdin.close()
    p2.wait()
    if p2.returncode != 0:
        if lesser:
            grass.fatal(
                _("No areas of size less than or equal to %f "
                  "hectares found.") % limit)
        else:
            grass.fatal(
                _("No areas of size greater than or equal to %f "
                  "hectares found.") % limit)
    grass.mapcalc("$outfile = $recfile", outfile=outfile, recfile=recfile)
Beispiel #27
0
def calculate_lfp(input, output, coords):
    prefix = "r_lfp_%d_" % os.getpid()

    # create the outlet vector map
    outlet = prefix + "outlet"
    p = grass.feed_command("v.in.ascii",
                           overwrite=True,
                           input="-",
                           output=outlet,
                           separator=",")
    p.stdin.write(coords)
    p.stdin.close()
    p.wait()
    if p.returncode != 0:
        grass.fatal(_("Cannot create the outlet vector map"))

    # convert the outlet vector map to raster
    try:
        grass.run_command("v.to.rast",
                          overwrite=True,
                          input=outlet,
                          output=outlet,
                          use="cat",
                          type="point")
    except CalledModuleError:
        grass.fatal(_("Cannot convert the outlet vector to raster"))

    # calculate the downstream flow length
    flds = prefix + "flds"
    try:
        grass.run_command("r.stream.distance",
                          overwrite=True,
                          flags="om",
                          stream_rast=outlet,
                          direction=input,
                          method="downstream",
                          distance=flds)
    except CalledModuleError:
        grass.fatal(_("Cannot calculate the downstream flow length"))

    # calculate the upstream flow length
    flus = prefix + "flus"
    try:
        grass.run_command("r.stream.distance",
                          overwrite=True,
                          flags="o",
                          stream_rast=outlet,
                          direction=input,
                          method="upstream",
                          distance=flus)
    except CalledModuleError:
        grass.fatal(_("Cannot calculate the upstream flow length"))

    # calculate the sum of downstream and upstream flow lengths
    fldsus = prefix + "fldsus"
    try:
        grass.run_command("r.mapcalc",
                          overwrite=True,
                          expression="%s=%s+%s" % (fldsus, flds, flus))
    except CalledModuleError:
        grass.fatal(
            _("Cannot calculate the sum of downstream and upstream flow lengths"
              ))

    # find the longest flow length
    p = grass.pipe_command("r.info", flags="r", map=fldsus)
    max = ""
    for line in p.stdout:
        line = line.rstrip("\n")
        if line.startswith("max="):
            max = line.split("=")[1]
            break
    p.wait()
    if p.returncode != 0 or max == "":
        grass.fatal(_("Cannot find the longest flow length"))

    min = float(max) - 0.0005

    # extract the longest flow path
    lfp = prefix + "lfp"
    try:
        grass.run_command("r.mapcalc",
                          overwrite=True,
                          expression="%s=if(%s>=%f, 1, null())" %
                          (lfp, fldsus, min))
    except CalledModuleError:
        grass.fatal(_("Cannot create the longest flow path raster map"))

    # thin the longest flow path raster map
    try:
        grass.run_command("r.thin", input=lfp, output=output)
    except CalledModuleError:
        grass.fatal(_("Cannot thin the longest flow path raster map"))

    # remove intermediate outputs
    grass.run_command("g.remove",
                      flags="f",
                      type="raster,vector",
                      pattern="%s*" % prefix)

    # write metadata
    tmphist = grass.tempfile()
    f = open(tmphist, "w+")
    f.write(os.environ["CMDLINE"])
    f.close()

    grass.run_command("r.support",
                      map=output,
                      title="Longest flow path",
                      loadhistory=tmphist,
                      description="generated by r.lfp")
    grass.try_remove(tmphist)
Beispiel #28
0
def main():
    raster = options["raster"]
    maskcats = options["maskcats"]
    vector = options["vector"]
    layer = options["layer"]
    cats = options["cats"]
    where = options["where"]
    remove = flags["r"]
    invert = flags["i"]

    if not remove and not raster and not vector:
        grass.fatal(_("Either parameter <raster> ot parameter <vector> is required"))

    mapset = grass.gisenv()["MAPSET"]
    exists = bool(grass.find_file("MASK", element="cell", mapset=mapset)["file"])

    if remove:
        # -> remove
        if exists:
            grass.run_command("g.remove", flags="f", quiet=True, type="rast", pattern="MASK")
            grass.message(_("Raster MASK removed"))
        else:
            grass.fatal(_("No existing MASK to remove"))
    else:
        # -> create
        if exists:
            if not grass.overwrite():
                grass.fatal(_("MASK already found in current mapset. Delete first or overwrite."))
            else:
                grass.warning(_("MASK already exists and will be overwritten"))
                grass.run_command("g.remove", flags="f", quiet=True, type="rast", pattern="MASK")

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

            if maskcats != "*" and not remove:
                if grass.raster_info(raster)["datatype"] != "CELL":
                    grass.fatal(
                        _(
                            "The raster map <%s> must be integer (CELL type) "
                            " in order to use the 'maskcats' parameter"
                        )
                        % raster
                    )

            p = grass.feed_command("r.reclass", input=raster, output="MASK", overwrite=True, rules="-")
            p.stdin.write("%s = 1" % maskcats)
            p.stdin.close()
            p.wait()
        elif vector:
            vector_name = grass.find_file(vector, "vector")["fullname"]
            if not vector_name:
                grass.fatal(_("Vector map <%s> not found") % vector)

            # parser bug?
            if len(cats) == 0:
                cats = None
            if len(where) == 0:
                where = None

            if grass.vector_info_topo(vector_name)["areas"] < 1:
                grass.warning(_("No area found in vector map <%s>. " "Creating a convex hull for MASK.") % vector_name)
                global tmp_hull
                tmp_hull = "tmp_hull_%d" % os.getpid()
                to_rast_input = tmp_hull
                # force 'flat' convex hull for 3D vector maps
                if 0 != grass.run_command(
                    "v.hull",
                    flags="f",
                    quiet=True,
                    input=vector_name,
                    output=tmp_hull,
                    layer=layer,
                    cats=cats,
                    where=where,
                ):
                    grass.fatal(_("Unable to create a convex hull for vector map <%s>") % vector_name)
            else:
                to_rast_input = vector_name

            env = os.environ.copy()
            if grass.verbosity() > 1:
                env["GRASS_VERBOSE"] = "1"
            grass.run_command(
                "v.to.rast",
                input=to_rast_input,
                layer=layer,
                output="MASK",
                use="val",
                val="1",
                type="area",
                cats=cats,
                where=where,
                env=env,
            )

        if invert:
            global tmp
            tmp = "r_mask_%d" % os.getpid()
            grass.run_command("g.rename", rast=("MASK", tmp), quiet=True)
            grass.message(_("Creating inverted raster MASK..."))
            grass.mapcalc("MASK = if(isnull($tmp), 1, null())", tmp=tmp)
            grass.verbose(_("Inverted raster MASK created"))
        else:
            grass.verbose(_("Raster MASK created"))

        grass.message(
            _(
                "All subsequent raster operations will be limited to "
                "the MASK area. Removing or renaming raster map named "
                "'MASK' will restore raster operations to normal."
            )
        )
Beispiel #29
0
def landscapeEvol(m, o, p, q, res, s, f):
    """
    Now define  "landscapeEvol",  our main block of code, here defined
    because of the way g.parser needs to be called with python codes for grass
    (see below)
    m = last iteration number,
    o = iteration number,
    p = prefx,
    q = statsout,
    res = resolution of input elev map,
    s = master list of lists of climate data
    f = name of text file to write stats to
    """

    # Get the process id to tag any temporary maps we make for easy clean up in the loop
    pid = os.getpid()

    # Get variables from user input
    elev = options["elev"]
    transp_eq = options["transp_eq"]
    initbdrk = options["initbdrk"]
    outdem = options["outdem"]
    outsoil = options["outsoil"]
    sdensity = options["sdensity"]
    K = options["k"]
    P = options["p"]
    C = options["c"]
    exp_m = options["exp_m"].split(",")
    exp_n = options["exp_n"].split(",")
    flowcontrib = options["flowcontrib"]
    convergence = options["convergence"]
    manningn = options["manningn"]
    p = options["prefx"]

    # Make some variables for temporary map names
    aspect = "%saspect%04d" % (p, o)
    flowacc = "%sflowacc%04d" % (p, o)
    flowdir = "%sflowdir%04d" % (p, o)
    flacclargenum = "%sflowacclargenum%04d" % (p, o)
    pc = "%spc%04d" % (p, o)
    tc = "%stc%04d" % (p, o)
    qsx = "%sQsx_%04d" % (p, o)
    qsy = "%sQsy_%04d" % (p, o)
    qsxdx = "%sDelta_Qsx_%04d" % (p, o)
    qsydy = "%sDelta_Qsy_%04d" % (p, o)
    rainexcess = "%s_rainfall_excess_map_%04d" % (p, o)
    tmpnetchange = "tmp%s_netchange%04d" % (pid, o)
    tmp90qle = "tmp%s_netchange_90qle%04d" % (pid, o)
    tmp10qle = "tmp%s_netchange_10qle%04d" % (pid, o)
    tmperosion = "tmp%s_erosion%04d" % (pid, o)
    tmpdep = "tmp%s_deposition%04d" % (pid, o)

    # List of temp maps to remove unless user wants to keep them all
    mapstoremove = [
        aspect,
        flowacc,
        flowdir,
        flacclargenum,
        pc,
        tc,
        rainexcess,
        tmpnetchange,
        tmp10qle,
        tmp90qle,
        tmperosion,
        tmpdep,
    ]

    # Variables that come in as a list of lists and can update with each iteration
    # masterlist = [R2,rain2,stormlength2,storms2,stormi2]
    R = s[0][m]
    rain = s[1][m]
    stormtimet = float(s[2][m]) * 3600.00  # Convert storm length to seconds
    storms = s[3][m]
    stormi = (float(s[4][m]) * stormtimet
              )  # Calculate the length of time at peak flow depth

    # Maps that will update at each iteration to record state of landscape
    old_dem = "%s%s%04d" % (p, outdem, m)
    old_soil = "%s%s%04d" % (p, outsoil, m)
    slope = "%sslope%04d" % (p, o)
    netchange = "%sED_rate%04d" % (p, o)
    new_dem = "%s%s%04d" % (p, outdem, o)
    new_soil = "%s%s%04d" % (p, outsoil, o)

    # If first iteration, use input maps. Otherwise, use maps generated from
    # previous iterations
    if o == 1:
        grass.run_command("g.copy", raster=elev + "," + old_dem, quiet=True)

    # Grab the number of cells in the starting DEM
    numcells = grass.parse_command(
        "r.univar",
        flags="g",
        map=old_dem,
    )["n"]

    # Calculate soil as difference between surface and bedrock
    grass.mapcalc(
        "${old_soil}=${old_dem}-${initbdrk}",
        overwrite=True,
        quiet=True,
        old_soil=old_soil,
        old_dem=old_dem,
        initbdrk=initbdrk,
    )

    grass.message("\n*************************\n" + "Iteration %s -- " % o +
                  "step 1/6: calculating slope\n" +
                  "*************************\n")
    grass.run_command("r.slope.aspect",
                      quiet=True,
                      elevation=old_dem,
                      aspect=aspect,
                      slope=slope)

    grass.message("\n*************************\n" + "Iteration %s -- " % o +
                  "step 2/6: calculating accumulated flow depths\n" +
                  "*************************\n")
    # Make map of rainfall excess (proportion each cell contributes to
    # downstrem flow) from flowcontrib. Note that if flowcontrib is a map, we
    # are just making a copy of it. This map is a percentage, but has to be
    # scaled from 0-100, because r.watershed will only allow values greater
    # than 1 as input in it's 'flow' variable. This creates a flow accumulation
    # map with large numbers, which will be divided by 100 after it is
    # made, bringing the values back down to what they should be.

    grass.mapcalc(
        "${rainexcess}=int(${flowcontrib})",
        quiet=True,
        rainexcess=rainexcess,
        flowcontrib=flowcontrib,
    )

    grass.run_command(
        "r.watershed",
        quiet=True,
        flags="a",
        elevation=old_dem,
        threshold=numcells,
        flow=rainexcess,
        accumulation=flacclargenum,
        drainage=flowdir,
        convergence=convergence,
    )

    grass.mapcalc(
        "${flowacc}=${flacclargenum}/100",
        quiet=True,
        flowacc=flowacc,
        flacclargenum=flacclargenum,
    )

    # again, do something different if we are only making an evaluation of cutoffs
    if flags["p"] is True:
        samplePoints(old_dem, aspect, slope, pc, tc, flowacc, p)

    grass.message("\n*************************\n" + "Iteration %s -- " % o +
                  "step 3/6: calculating sediment transport rates \n" +
                  "*************************\n")
    # Figure out which transport equation to run. All equations estimate transport capacity as kg/m.s. Note that we integrate the step to calculate the Tc in the east and west directions, to simplify the divergence calculations in the next step (i.e., to reduce the overall number of mapcalc statements and intermediate maps)

    if transp_eq == "StreamPower":
        # Stream power equation: Tc=Kt*gw*1/N*h^m*B^n
        # where: h = depth of flow = (i*A)/(0.595*t)
        # and: B = change in slope
        # GIS Implementation:
        # Tc=K*C*P*gw*(1/N)*((i*A)/(0.595*t))^m*(tan(S)^n)
        # Variables:
        # Tc=Transport Capacity [kg/meters.second]
        # K*C*P=Kt=mitigating effects of soil type, vegetation cover, and landuse practices. [unitless]
        # gw=Hydrostatic pressure of water 9810 [kg/m2.second]
        # N=Manning's coefficient ~0.3-0.6 for different types of stream channesl [unitless]
        # i=rainfall intentsity [m/rainfall event]
        # A=uplsope accumulated area per contour (cell) width [m2/m] = [m]
        # 0.595 = constant for time-lagged peak flow (assumes symmetrical unit hydrograph)
        # t=length of rainfall event [seconds]
        # S=topographic slope [degrees]
        # m = transport coefficient for upslope area [unitless]
        # n transport coefficient for slope [unitless]
        # SLOPE VERSISON
        e1 = """${qsx}=${K}*${C}*${P} * exp(${manningn}, -1) * 9810. * \
        exp((((${rain}/1000.)*${flowacc})/(0.595*${stormtimet})), \
        graph(${flowacc}, ${exp_m1a},${exp_m1b}, ${exp_m2a},${exp_m2b}) ) * \
        exp(tan(${slope}), graph(${slope}, ${exp_n1a},${exp_n1b}, ${exp_n2a},${exp_n2b}))\
        * cos(${aspect})"""

        e2 = """${qsy}=${K}*${C}*${P} * exp(${manningn}, -1) * 9810. * \
        exp((((${rain}/1000.)*${flowacc})/(0.595*${stormtimet})), \
        graph(${flowacc}, ${exp_m1a},${exp_m1b}, ${exp_m2a},${exp_m2b})) * \
        exp(tan(${slope}),  graph(${slope}, ${exp_n1a},${exp_n1b}, ${exp_n2a},${exp_n2b}))\
        * sin(${aspect})"""

    elif transp_eq == "ShearStress":
        # Shear stress equation: Tc=Kt*tau^m  (critical shear stress assumed to be 0)
        # where: tau = shear stress = gw*h*B
        # and: S =  change in slope
        # and: h = depth of flow = (i*A)/(0.595*t)
        # GIS Implmentation:
        # Tc=K*C*P*(gw*((i*A)/(0.595*t)*(tan(S))))^m
        # Variables:
        # Tc=Transport Capacity [kg/meters.second]
        # K*C*P=Kt=mitigating effects of soil type, vegetation cover, and landuse practices. [unitless]
        # gw=Hydrostatic pressure of water 9810 [kg/m2.second]
        # N=Manning's coefficient ~0.3-0.6 for different types of stream channesl [unitless]
        # i=rainfall intentsity [m/rainfall event]
        # A=uplsope accumulated area per contour (cell) width [m2/m] = [m]
        # 0.595 = constant for time-lagged peak flow (assumes symmetrical unit hydrograph)
        # t=length of rainfall event [seconds]
        # B=topographic slope [degrees]
        # m = transport coefficient (here assumed to be scaled to upslope area) [unitless]

        e1 = """${qsx}=(${K}*${C}*${P} * \
        exp(9810.*(((${rain}/1000)*${flowacc})/(0.595*${stormtimet}))*tan(${slope}), \
        graph(${flowacc}, ${exp_n1a},${exp_n1b}, ${exp_n2a},${exp_n2b}))) * \
        cos(${aspect})"""

        e2 = """${qsy}=(${K}*${C}*${P} * \
        exp(9810.*(((${rain}/1000)*${flowacc})/(0.595*${stormtimet}))*tan(${slope}), \
        graph(${flowacc}, ${exp_n1a},${exp_n1b}, ${exp_n2a},${exp_n2b}) )) * \
        sin(${aspect})"""

    elif transp_eq == "USPED":
        # USPED equation: Tc=R*K*C*P*A^m*B^n
        # where: B = change in slope
        # GIS Implementation:
        # Tc=R*K*C*P*A^m*tan(S)^n
        # Variables:
        # Tc=Transport Capacity [kg/meters.second]
        # R=Rainfall intensivity factor [MJ.mm/ha.h.yr]
        # A=uplsope accumulated area per contour (cell) width [m2/m] = [m]
        # S=topographic slope [degrees]
        # m = transport coefficient for upslope area [unitless]
        # n transport coefficient for slope [unitless]

        e1 = """${qsx}=((${R}*${K}*${C}*${P}*\
        exp((${flowacc}*${res}),graph(${flowacc}, ${exp_m1a},${exp_m1b}, ${exp_m2a},${exp_m2b}))*\
        exp(sin(${slope}), graph(${slope}, ${exp_n1a},${exp_n1b}, ${exp_n2a},${exp_n2b})))\
        * cos(${aspect}))"""

        e2 = """${qsy}=((${R}*${K}*${C}*${P}*\
        exp((${flowacc}*${res}),graph(${flowacc}, ${exp_m1a},${exp_m1b}, ${exp_m2a},${exp_m2b}))*\
        exp(sin(${slope}), graph(${slope}, ${exp_n1a},${exp_n1b}, ${exp_n2a},${exp_n2b})))\
        * sin(${aspect}))"""

    else:
        grass.fatal(
            'You have entered a non-viable tranport equation name. Please ensure option "transp_eq" is one of "StreamPower," "ShearStress," or "USPED."'
        )

    # Actually do the mapcalc statement for chosen transport equation
    x = grass.mapcalc_start(
        e1,
        quiet=True,
        qsx=qsx,
        slope=slope,
        aspect=aspect,
        R=R,
        K=K,
        C=C,
        P=P,
        res=res,
        flowacc=flowacc,
        rain=rain,
        stormtimet=stormtimet,
        stormi=stormi,
        exp_m1a=exp_m[0],
        exp_m1b=exp_m[1],
        exp_m2a=exp_m[2],
        exp_m2b=exp_m[3],
        exp_n1a=exp_n[0],
        exp_n1b=exp_n[1],
        exp_n2a=exp_n[2],
        exp_n2b=exp_n[3],
        manningn=manningn,
    )

    y = grass.mapcalc_start(
        e2,
        quiet=True,
        qsy=qsy,
        slope=slope,
        aspect=aspect,
        R=R,
        K=K,
        C=C,
        P=P,
        res=res,
        flowacc=flowacc,
        rain=rain,
        stormtimet=stormtimet,
        stormi=stormi,
        exp_m1a=exp_m[0],
        exp_m1b=exp_m[1],
        exp_m2a=exp_m[2],
        exp_m2b=exp_m[3],
        exp_n1a=exp_n[0],
        exp_n1b=exp_n[1],
        exp_n2a=exp_n[2],
        exp_n2b=exp_n[3],
        manningn=manningn,
    )
    x.wait()
    y.wait()

    grass.message(
        "\n*************************\n" + "Iteration %s -- " % o +
        "step 4/6: calculating divergence/difference of sediment transport and the actual amount of erosion or deposition in vertical meters/cell/year\n"
        + "*************************\n")

    # Taking divergence of transport capacity Tc converts kg/m.s to kg/m2.s
    sax = grass.start_command("r.slope.aspect",
                              quiet=True,
                              elevation=qsx,
                              dx=qsxdx)
    say = grass.start_command("r.slope.aspect",
                              quiet=True,
                              elevation=qsy,
                              dy=qsydy)

    sax.wait()
    say.wait()

    # Now convert output of divergence to calculated erosion and deposition in
    # vertical meters of elevation change. Add back the divergence in EW and NS
    # directions. Units are in kg/m2.s, so start by dividing by soil density
    # [kg/m3] to get m/s elevation change (for USPED that is m/year already,
    # but not for the shear stress or stream power).
    # For shear stress and stream power, also multiply by the number
    # of seconds at peak flow depth (stormi) and then by the number of erosive
    # storms per year to get m/year elevation change.
    if transp_eq == "USPED":
        ed = """${netchange}=((${qsxdx}+${qsydy})/${sdensity})"""
        grass.mapcalc(
            ed,
            quiet=True,
            netchange=tmpnetchange,
            qsxdx=qsxdx,
            qsydy=qsydy,
            sdensity=sdensity,
        )
    else:
        ed = """${netchange}=((${qsxdx}+${qsydy})/${sdensity})*${stormi}*${storms}"""
        grass.mapcalc(
            ed,
            quiet=True,
            netchange=tmpnetchange,
            qsxdx=qsxdx,
            qsydy=qsydy,
            sdensity=sdensity,
            stormi=stormi,
            storms=storms,
        )
    # Apply smoothing to the output to remove some spikes. Map will only be smoothed for values above the 90th quantile and below the 10th quantile (i.e., only extreme values will be smoothed)
    if flags["m"] is True:
        a = grass.start_command(
            "r.neighbors",
            quiet=True,
            input=tmpnetchange,
            output=tmp10qle,
            method="quantile",
            size=5,
            quantile=0.1,
        )
        b = grass.start_command(
            "r.neighbors",
            quiet=True,
            input=tmpnetchange,
            output=tmp90qle,
            method="quantile",
            size=5,
            quantile=0.9,
        )
        a.wait()
        b.wait()
        smoother = """${netchange}=if(${tmpnetchange}<${tmp10qle}, ${tmp10qle}, if(${tmpnetchange}>${tmp90qle}, ${tmp90qle}, ${tmpnetchange}))"""
        grass.mapcalc(
            smoother,
            quiet=True,
            netchange=netchange,
            tmpnetchange=tmpnetchange,
            tmp90qle=tmp90qle,
            tmp10qle=tmp10qle,
        )
    else:
        grass.run_command("g.rename",
                          quiet=True,
                          raster=tmpnetchange + "," + netchange)

    grass.message(
        "\n*************************\n" + "Iteration %s -- " % o +
        "step 5/6: calculating terrain evolution and new soil depths\n" +
        " *************************\n")
    # Compute elevation changes: addition of ED change to old DEM.
    # This mapcalc statement first checks the amount of erodable soil in a given
    # cell against the amount of erosion calculated, and keeps the cell from
    # eroding past this amount (if there is soil, then if the amount of erosion
    # is more than the amount of soil, just remove all the soil and stop, else
    # remove the amount of caclulated erosion. It also runs an error catch that
    # checks to make sure that soil depth is not negative (could happen, I
    # suppose), and if it is, corrects it). Finally, do patch-job to catch the
    # shrinking edge problem (the edge cells have no upstream cell, so get
    # turned null in the calculations in step 4)

    e = """${new_dem} = eval(x=if(${old_soil} > 0.0 && (-1*${netchange}) <= ${old_soil}, ${netchange}, \
           if((-1*${netchange}) > ${old_soil}, (-1*${old_soil}), 0)), \
           y=(${old_dem} + x), if(isnull(y), ${old_dem}, y))"""
    grass.mapcalc(
        e,
        quiet=True,
        new_dem=new_dem,
        old_soil=old_soil,
        old_dem=old_dem,
        netchange=netchange,
    )

    # Calculate new soil depths by subtracting initial bedrock elevations from
    # the new DEM.
    e = """${new_soil} = if((${new_dem} - ${initbdrk}) < 0, 0, (${new_dem} - ${initbdrk}))"""
    grass.mapcalc(e,
                  quiet=True,
                  new_soil=new_soil,
                  new_dem=new_dem,
                  initbdrk=initbdrk)

    # Set colors for elevation, soil, and ED maps
    grass.run_command("r.colors", quiet=True, map=new_dem, color="srtm")

    sdcolors = [
        "100% 0:249:47", "20% 78:151:211", "6% 194:84:171", "0% 227:174:217"
    ]
    sdc = grass.feed_command("r.colors", quiet=True, map=new_soil, rules="-")
    sdc.stdin.write("\n".join(sdcolors))
    sdc.stdin.close()

    nccolors = [
        "100 127:0:255",
        "1 0:0:255",
        ".1 0:255:0",
        "0.001 152:251:152",
        "0 250:250:250",
        "-0.001 255:255:50",
        "-.1 255:127:0",
        "-1 255:0:0",
        "-100 127:0:255",
    ]
    ncc = grass.feed_command("r.colors", quiet=True, map=netchange, rules="-")
    ncc.stdin.write("\n".join(nccolors))
    ncc.stdin.close()

    sdc.wait()
    ncc.wait()

    grass.message("\n*************************\n" + "Iteration %s -- " % o +
                  "step 6/6: writing stats to output file\n" +
                  "*************************\n")
    # Make some temp maps of just erosion rate and just deposition rates
    e = """${tmperosion}=if(${netchange} < -0, ${netchange}, null())"""
    ero1 = grass.mapcalc_start(e,
                               quiet=True,
                               tmperosion=tmperosion,
                               netchange=netchange)

    e = """${tmpdep}=if(${netchange} > 0, ${netchange}, null())"""
    dep1 = grass.mapcalc_start(e,
                               quiet=True,
                               tmpdep=tmpdep,
                               netchange=netchange)

    ero1.wait()
    dep1.wait()

    # Grab the stats from these temp files and save them to dictionaries
    erosstats = grass.parse_command("r.univar",
                                    flags="ge",
                                    percentile="1",
                                    map=tmperosion)
    depostats = grass.parse_command("r.univar",
                                    flags="ge",
                                    percentile="99",
                                    map=tmpdep)

    # Finish gathering stats (just need the soil depth stats now)
    soilstats = grass.parse_command("r.univar",
                                    flags="ge",
                                    map=new_soil,
                                    percentile="99")

    # Write stats to a new line in the stats file
    # HEADER of the file should be: ',,Mean Values,,,,Standard Deviations,,,,Totals,,,Additional Stats\nIteration,,Mean Erosion,Mean Deposition,Mean Soil Depth,,Standard Deviation Erosion,Standard Deviation Deposition,Standard Deviation Soil Depth,,Total Sediment Eroded,Total Sediment Deposited,,Minimum Erosion,First Quartile Erosion,Median Erosion,Third Quartile Erosion,Maximum Erosion,Original Un-smoothed Maximum Erosion,,Minimum Deposition,First Quartile Deposition,Median Deposition,Third Quartile Deposition,Maximum Deposition,Original Un-smoothed Maximum Deposition,,Minimum Soil Depth,First Quartile Soil Depth,Median Soil Depth,Third Quartile Soil Depth,Maximum Soil Depth'

    f.write("\n%s" % o + ",," + erosstats["mean"] + "," + depostats["mean"] +
            "," + soilstats["mean"] + ",," + erosstats["stddev"] + "," +
            depostats["stddev"] + "," + soilstats["stddev"] + ",," +
            erosstats["sum"] + "," + depostats["sum"] + ",," +
            erosstats["max"] + "," + erosstats["third_quartile"] + "," +
            erosstats["median"] + "," + erosstats["first_quartile"] + "," +
            erosstats["min"] + "," + depostats["min"] + "," +
            depostats["first_quartile"] + "," + depostats["median"] + "," +
            depostats["third_quartile"] + "," + depostats["max"] + "," +
            soilstats["min"] + "," + soilstats["first_quartile"] + "," +
            soilstats["median"] + "," + soilstats["third_quartile"] + "," +
            soilstats["max"])

    # Cleanup temporary files
    if flags["k"] is True:
        grass.message("\nTemporary maps will NOT be deleted!!!!\n")
    else:
        grass.message("\nCleaning up temporary maps...\n\n")
        # Check all the flag options, and add to list of maps to delete
        if flags["s"] is True:
            grass.message("Keeping Slope map.")
        else:
            mapstoremove.append(slope)
        if flags["d"] is True:
            grass.message("Not keeping Soil Depth map.")
            mapstoremove.append(old_soil)
            # Check if this is the last year and remove the "new-soil" map too
            if o == int(options["number"]):
                mapstoremove.append(new_soil)
        else:
            # Check if this is the first year, and if so, remove the temporary initial soil depths map
            if o <= 1:
                grass.message(("%s%s%04d" % (p, outsoil, m)))
                mapstoremove.append("%s%s%04d" % (p, outsoil, m))
        if flags["e"] is True:
            grass.message(
                "Keeping delta Transport Capacity (divergence) maps.")
        else:
            mapstoremove.extend([qsxdx, qsydy])
        if flags["t"] is True:
            grass.message("Keeping Transport Capacity maps.")
        else:
            mapstoremove.extend([qsx, qsy])
        if flags["r"] is True:
            grass.message("Not keeping an Erosion and Deposition rate map.")
            mapstoremove.append(netchange)
        if len(mapstoremove) == 0:
            pass
        else:
            grass.run_command(
                "g.remove",
                quiet=True,
                flags="f",
                type="rast",
                name=",".join(mapstoremove),
            )

    grass.message("\n*************************\n" +
                  "Done with Iteration %s " % o +
                  "\n*************************\n")
    return 0
Beispiel #30
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))
Beispiel #31
0
def main():
    raster = options['raster']
    maskcats = options['maskcats']
    vector = options['vector']
    layer = options['layer']
    cats = options['cats']
    where = options['where']
    remove = flags['r']
    invert = flags['i']

    if not remove and not raster and not vector:
        grass.fatal(
            _("Either parameter <raster> ot parameter <vector> is required"))

    mapset = grass.gisenv()['MAPSET']
    exists = bool(
        grass.find_file('MASK', element='cell', mapset=mapset)['file'])

    if remove:
        # -> remove
        if exists:
            grass.run_command('g.remove',
                              flags='f',
                              quiet=True,
                              type='raster',
                              name='MASK')
            grass.message(_("Raster MASK removed"))
        else:
            grass.fatal(_("No existing MASK to remove"))
    else:
        # -> create
        if exists:
            if not grass.overwrite():
                grass.fatal(
                    _("MASK already found in current mapset. Delete first or overwrite."
                      ))
            else:
                grass.warning(_("MASK already exists and will be overwritten"))
                grass.run_command('g.remove',
                                  flags='f',
                                  quiet=True,
                                  type='raster',
                                  name='MASK')

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

            if maskcats != '*' and not remove:
                if grass.raster_info(raster)['datatype'] != "CELL":
                    grass.fatal(
                        _("The raster map <%s> must be integer (CELL type) "
                          " in order to use the 'maskcats' parameter") %
                        raster)

            p = grass.feed_command('r.reclass',
                                   input=raster,
                                   output='MASK',
                                   overwrite=True,
                                   rules='-')
            p.stdin.write("%s = 1" % maskcats)
            p.stdin.close()
            p.wait()
        elif vector:
            vector_name = grass.find_file(vector, 'vector')['fullname']
            if not vector_name:
                grass.fatal(_("Vector map <%s> not found") % vector)

            # parser bug?
            if len(cats) == 0:
                cats = None
            if len(where) == 0:
                where = None

            if grass.vector_info_topo(vector_name)['areas'] < 1:
                grass.warning(
                    _("No area found in vector map <%s>. "
                      "Creating a convex hull for MASK.") % vector_name)
                global tmp_hull
                tmp_hull = "tmp_hull_%d" % os.getpid()
                to_rast_input = tmp_hull
                # force 'flat' convex hull for 3D vector maps
                try:
                    grass.run_command('v.hull',
                                      flags='f',
                                      quiet=True,
                                      input=vector_name,
                                      output=tmp_hull,
                                      layer=layer,
                                      cats=cats,
                                      where=where)
                except CalledModuleError:
                    grass.fatal(
                        _("Unable to create a convex hull for vector map <%s>")
                        % vector_name)
            else:
                to_rast_input = vector_name

            env = os.environ.copy()
            if grass.verbosity() > 1:
                env['GRASS_VERBOSE'] = '1'
            grass.run_command('v.to.rast',
                              input=to_rast_input,
                              layer=layer,
                              output='MASK',
                              use='val',
                              val='1',
                              type='area',
                              cats=cats,
                              where=where,
                              env=env)

        if invert:
            global tmp
            tmp = "r_mask_%d" % os.getpid()
            grass.run_command('g.rename', raster=('MASK', tmp), quiet=True)
            grass.message(_("Creating inverted raster MASK..."))
            grass.mapcalc("MASK = if(isnull($tmp), 1, null())", tmp=tmp)
            grass.verbose(_("Inverted raster MASK created"))
        else:
            grass.verbose(_("Raster MASK created"))

        grass.message(
            _("All subsequent raster operations will be limited to "
              "the MASK area. Removing or renaming raster map named "
              "'MASK' will restore raster operations to normal."))
Beispiel #32
0
def main():
    global temp_dist, temp_src

    input = options['input']
    output = options['output']
    distances = options['distances']
    units = options['units']
    zero = flags['z']

    tmp = str(os.getpid())
    temp_dist = "r.buffer.tmp.%s.dist" % tmp
    temp_src = "r.buffer.tmp.%s.src" % tmp

    #check if input file exists
    if not grass.find_file(input)['file']:
	grass.fatal(_("<%s> does not exist.") % input)

    scale = scales[units]

    distances  = distances.split(',')
    distances1 = [scale * float(d) for d in distances]
    distances2 = [d * d for d in distances1]

    s = grass.read_command("g.proj", flags='j')
    kv = grass.parse_key_val(s)
    if kv['+proj'] == 'longlat':
	metric = 'geodesic'
    else:
	metric = 'squared'

    grass.run_command('r.grow.distance',  input = input, metric = metric,
		      distance = temp_dist)

    if zero:
	exp = "$temp_src = if($input == 0,null(),1)"
    else:
	exp = "$temp_src = if(isnull($input),null(),1)"

    grass.message(_("Extracting buffers (1/2)..."))
    grass.mapcalc(exp, temp_src = temp_src, input = input)

    exp = "$output = if(!isnull($input),$input,%s)"
    for n, dist2 in enumerate(distances2):
	exp %= "if($dist <= %f,%d,%%s)" % (dist2,n + 2)
    exp %= "null()"

    grass.message(_("Extracting buffers (2/2)..."))
    grass.mapcalc(exp, output = output, input = temp_src, dist = temp_dist)

    p = grass.feed_command('r.category', map = output, rules = '-')
    p.stdin.write("1:distances calculated from these locations\n")
    d0 = "0"
    for n, d in enumerate(distances):
	p.stdin.write("%d:%s-%s %s\n" % (n + 2, d0, d, units))
	d0 = d
    p.stdin.close()
    p.wait()

    grass.run_command('r.colors', map = output, color = 'rainbow')

    # write cmd history:
    grass.raster_history(output)
Beispiel #33
0
def main():
    table = options["table"]
    column = options["column"]
    otable = options["other_table"]
    ocolumn = options["other_column"]
    if options["subset_columns"]:
        scolumns = options["subset_columns"].split(",")
    else:
        scolumns = None

    database = options["database"]
    driver = options["driver"]

    # this error handling is completely different among th db.* scripts - FIX
    if not database:
        database = None
    if not driver:
        driver = None

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

    # describe input table
    all_cols_tt = grass.db_describe(table, driver=driver,
                                    database=database)["cols"]
    if not all_cols_tt:
        grass.fatal(_("Unable to describe table <%s>") % table)
    found = False

    # check if column is in input table
    if column not in [col[0] for col in all_cols_tt]:
        grass.fatal(_("Column <%s> not found in table <%s>") % (column, table))

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

    # check if ocolumn is in 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))

    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:
            p = grass.feed_command("db.execute",
                                   input="-",
                                   database=database,
                                   driver=driver)
            p.stdin.write("ALTER TABLE %s ADD COLUMN %s" % (table, colspec))
            grass.debug("ALTER TABLE %s ADD COLUMN %s" % (table, colspec))
            p.stdin.close()
            if p.wait() != 0:
                grass.fatal(_("Unable to add column <%s>.") % colname)

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

    return 0
Beispiel #34
0
    def import_cloud_masks(self, area_threshold, prob_threshold, output,
                           shadows, reproject):
        try:
            if os.environ["GRASS_OVERWRITE"] == "1":
                overwrite = True
        except Exception as e:
            overwrite = False

        # Import cloud masks for L2A products
        files_L2A = self._filter("MSK_CLDPRB_20m.jp2")

        for f in files_L2A:
            safe_dir = os.path.dirname(f).split(os.path.sep)[-4]
            items = safe_dir.split("_")

            # Define names of final & temporary maps
            map_name = "_".join([items[5], items[2], "MSK", "CLOUDS"])
            clouds_imported = "_".join([items[5], items[2], "cloudprob"])
            clouds_selected = "_".join([items[5], items[2], "clouds_selected"])
            shadows_imported = "_".join([items[5], items[2], "shadows"])
            shadows_selected = "_".join(
                [items[5], items[2], "shadows_selected"])
            mask_selected = "_".join([items[5], items[2], "mask_selected"])
            mask_cleaned = "_".join([items[5], items[2], "mask_cleaned"])

            self._map_list.extend([
                clouds_imported,
                clouds_selected,
                shadows_imported,
                shadows_selected,
                mask_selected,
                mask_cleaned,
            ])

            # check if mask alrady exist
            if gs.find_file(name=map_name,
                            element=output)["file"] and not overwrite:
                gs.message(
                    _("option <output>: <{}> exists. To overwrite, use the --overwrite flag"
                      .format(map_name)))
                continue

            try:
                # Import & Threshold cloud probability layer
                gs.message(
                    _("Importing cloud mask for {}").format("_".join(
                        [items[5], items[2]])))
                if reproject:
                    self._args["resolution_value"] = self._raster_resolution(f)
                    self._args["resample"] = "bilinear"
                    gs.run_command("r.import",
                                   input=f,
                                   output=clouds_imported,
                                   **self._args)
                else:
                    gs.run_command("r.in.gdal",
                                   input=f,
                                   output=clouds_imported,
                                   **self._args)
                gs.use_temp_region()
                gs.run_command("g.region", raster=clouds_imported)
                gs.mapcalc(
                    f"{clouds_selected} = if({clouds_imported} >= {prob_threshold}, 1, 0)"
                )
                gs.del_temp_region()

                # Add shadow mask
                if shadows:
                    try:
                        shadow_file = self._filter("_".join(
                            [items[5], items[2], "SCL_20m.jp2"]))
                        if reproject:
                            self._args[
                                "resolution_value"] = self._raster_resolution(
                                    shadow_file[0])
                            self._args["resample"] = "nearest"
                            gs.run_command(
                                "r.import",
                                input=shadow_file,
                                output=shadows_imported,
                                **self._args,
                            )
                        else:
                            gs.run_command(
                                "r.in.gdal",
                                input=shadow_file,
                                output=shadows_imported,
                                **self._args,
                            )

                        gs.use_temp_region()
                        gs.run_command("g.region", raster=shadows_imported)
                        gs.mapcalc(
                            f"{shadows_selected} = if({shadows_imported} == 3, 2, 0)"
                        )
                        gs.mapcalc(
                            f"{mask_selected} = max({shadows_selected},{clouds_selected})"
                        )
                        gs.del_temp_region()
                    except Exception as e:
                        gs.warning(
                            _("Unable to import shadows for {}. Error: {}").
                            format("_".join([items[5], items[2]]), e))

                else:
                    gs.run_command("g.rename",
                                   quiet=True,
                                   raster=(clouds_selected, mask_selected))

                gs.use_temp_region()
                gs.run_command("g.region", raster=mask_selected)

                # Cleaning small patches
                try:
                    gs.run_command(
                        "r.reclass.area",
                        input=mask_selected,
                        output=mask_cleaned,
                        value=area_threshold,
                        mode="greater",
                    )
                except Exception as e:
                    pass  # error already printed

                # Extract & Label clouds (and shadows)
                gs.run_command("r.null", map=mask_cleaned, setnull="0")

                labels = ["1:clouds", "2:shadows"]
                labelling = gs.feed_command("r.category",
                                            map=mask_cleaned,
                                            separator=":",
                                            rules="-")
                labelling.stdin.write("\n".join(labels).encode())
                labelling.stdin.close()
                labelling.wait()

                info_stats = gs.parse_command("r.stats",
                                              input=mask_cleaned,
                                              flags="p")

                # Create final cloud (and shadow) mask & display areal statistics
                if output == "vector":
                    gs.run_command(
                        "r.to.vect",
                        input=mask_cleaned,
                        output=map_name,
                        type="area",
                        flags="s",
                    )
                    colours = ["1 230:230:230", "2 60:60:60"]
                    colourise = gs.feed_command(
                        "v.colors",
                        map=map_name,
                        use="attr",
                        column="value",
                        rules="-",
                        quiet=True,
                    )
                    colourise.stdin.write("\n".join(colours).encode())
                    colourise.stdin.close()
                    colourise.wait()
                    gs.vector_history(map_name)

                else:
                    gs.run_command("g.rename",
                                   quiet=True,
                                   raster=(mask_cleaned, map_name))
                    colours = ["1 230:230:230", "2 60:60:60"]
                    colourise = gs.feed_command("r.colors",
                                                map=map_name,
                                                rules="-",
                                                quiet=True)
                    colourise.stdin.write("\n".join(colours).encode())
                    colourise.stdin.close()
                    colourise.wait()
                    gs.raster_history(map_name)

                gs.message(
                    _("Areal proportion of masked clouds:{}").format(
                        [key.split()[1] for key in info_stats][0]))
                if shadows:
                    if len(info_stats) > 2:
                        gs.message(
                            _("Areal proportion of masked shadows:{}").format(
                                [key.split()[1] for key in info_stats][1]))
                    else:
                        gs.message(_("Areal proportion of masked shadows:0%"))

                gs.del_temp_region()

            except Exception as e:
                gs.del_temp_region()
                gs.warning(
                    _("Unable to import cloud mask for {}. Error: {}").format(
                        "_".join([items[5], items[2]]), e))

        # Import of simplified cloud masks for Level-1C products
        all_files = self._filter("MSK_CLOUDS_B00.gml")
        files_L1C = []

        for f in all_files:
            safe_dir = os.path.dirname(f).split(os.path.sep)[-4]
            if safe_dir not in [
                    os.path.dirname(file).split(os.path.sep)[-4]
                    for file in files_L2A
            ]:
                files_L1C.append(f)

        if len(files_L1C) > 0:
            from osgeo import ogr

            for f in files_L1C:
                safe_dir = os.path.dirname(f).split(os.path.sep)[-4]
                items = safe_dir.split("_")

                # Define names of final & temporary maps
                map_name = "_".join([items[5], items[2], "MSK", "CLOUDS"])
                clouds_imported = "_".join(
                    [items[5], items[2], "clouds_imported"])
                mask_cleaned = "_".join([items[5], items[2], "mask_cleaned"])
                self._map_list.extend([clouds_imported, mask_cleaned])

                # check if mask alrady exist
                if (gs.find_file(name=map_name, element=output)["file"]
                        and not overwrite):
                    gs.fatal(
                        _("option <output>: <{}> exists. To overwrite, use the --overwrite flag"
                          .format(map_name)))
                    continue

                # check if any OGR layer
                dsn = ogr.Open(f)
                layer_count = dsn.GetLayerCount()
                dsn.Destroy()
                if layer_count < 1:
                    gs.info(
                        "No clouds layer found in <{}>. Import skipped".format(
                            f))
                    continue

                # Import cloud layer
                try:
                    gs.message(
                        _("Importing cloud mask for {}").format("_".join(
                            [items[5], items[2]])))
                    gs.run_command(
                        "v.import",
                        input=f,
                        output=clouds_imported,
                        extent=options["extent"],
                        flags="o" if flags["o"] else None,
                        quiet=True,
                    )

                    gs.use_temp_region()
                    gs.run_command("g.region", vector=clouds_imported)

                    # Cleaning small patches
                    gs.run_command(
                        "v.clean",
                        input=clouds_imported,
                        output=mask_cleaned,
                        tool="rmarea",
                        threshold=area_threshold,
                    )

                    # Calculating info stats
                    gs.run_command("v.db.addcolumn",
                                   map=mask_cleaned,
                                   columns="value_num INT")
                    gs.run_command("v.db.update",
                                   map=mask_cleaned,
                                   column="value_num",
                                   value=1)
                    gs.run_command(
                        "v.to.rast",
                        input=mask_cleaned,
                        output=mask_cleaned,
                        use="attr",
                        attribute_column="value_num",
                        quiet=True,
                    )
                    info_stats = gs.parse_command("r.stats",
                                                  input=mask_cleaned,
                                                  flags="p")

                    # Create final cloud mask output
                    if output == "vector":
                        gs.run_command("g.rename",
                                       quiet=True,
                                       vector=(mask_cleaned, map_name))
                        colours = ["1 230:230:230"]
                        colourise = gs.feed_command(
                            "v.colors",
                            map=map_name,
                            use="attr",
                            column="value_num",
                            rules="-",
                            quiet=True,
                        )
                        colourise.stdin.write("\n".join(colours).encode())
                        colourise.stdin.close()
                        colourise.wait()
                        gs.vector_history(map_name)

                    else:
                        gs.run_command("g.rename",
                                       quiet=True,
                                       raster=(mask_cleaned, map_name))
                        colours = ["1 230:230:230"]
                        colourise = gs.feed_command("r.colors",
                                                    map=map_name,
                                                    rules="-",
                                                    quiet=True)
                        colourise.stdin.write("\n".join(colours).encode())
                        colourise.stdin.close()
                        colourise.wait()
                        gs.raster_history(map_name)

                    # Display messages & statistics
                    if shadows:
                        gs.warning(
                            _("Level1 product: No shadow mask for {}").format(
                                "_".join([items[5], items[2]])))

                    gs.message(
                        _("Areal proportion of masked clouds:{}").format(
                            [key.split()[1] for key in info_stats][0]))

                    gs.del_temp_region()

                except Exception as e:
                    gs.del_temp_region()
                    gs.warning(
                        _("Unable to import cloud mask for {}. Error: {}").
                        format("_".join([items[5], items[2]]), e))
Beispiel #35
0
def main():
    try:
        import projpicker as ppik
    except ImportError:
        grass.fatal(
            _("ProjPicker not installed. Use 'pip install projpicker'"))

    coords = options["coordinates"]
    operator = options["operator"]
    query = options["query"]
    infile = options["input"]
    outfile = options["output"]
    fmt = options["format"]
    separator = options["separator"]
    bbox_map = options["bbox_map"]
    overwrite = grass.overwrite()

    latlon = flags["l"]
    print_geoms = flags["p"]
    no_header = flags["n"]
    single = flags["1"]
    start_gui = flags["g"]

    if bbox_map and grass.parse_command("g.proj",
                                        flags="g")["unit"] != "degree":
        grass.fatal(_("Cannot create vector in degree in a non-degree mapset"))

    # ppik.projpicker() appends input file contents to geometries from
    # arguments, but it can be confusing and is not supported in this module
    if coords:
        query = f"{operator}"
        coords = coords.split(",")
        for x, y in zip(coords[0::2], coords[1::2]):
            if latlon:
                x, y = y, x
            query += f" {y},{x}"

    if infile:
        geoms = ppik.read_file(infile)
    else:
        geoms = query.split()
        n = len(geoms)
        idx = []
        i = 0
        while i < n - 1:
            m = re.match("""^(|unit=)(["'])(.*)$""", geoms[i])
            if m:
                geoms[i] = m[1] + m[3]
                quote = m[2]
                if geoms[i].endswith(quote):
                    geoms[i] = geoms[i][:-len(quote)]
                else:
                    for j in range(i + 1, n):
                        idx.append(j)
                        m = re.match(f"^(.*){quote}$", geoms[j])
                        if m:
                            geoms[i] += f" {m[1]}"
                            break
                        else:
                            geoms[i] += f" {geoms[j]}"
                    i = j
            i += 1
        for i in reversed(idx):
            del geoms[i]

    if separator == "pipe for plain; newline for srid":
        if fmt == "plain":
            separator = "|"
        elif fmt == "srid":
            separator = "\n"
    else:
        separator = grass.utils.separator(separator)

    bbox = ppik.projpicker(
        geoms=geoms,
        outfile=outfile,
        fmt=fmt,
        no_header=no_header,
        separator=separator,
        print_geoms=print_geoms,
        overwrite=overwrite,
        start_gui=start_gui,
        single=single,
    )

    if bbox_map:
        p = grass.feed_command(
            "v.in.ascii",
            input="-",
            output=bbox_map,
            format="standard",
            flags="n",
        )
        nbbox = len(bbox)
        for i in range(0, nbbox):
            b = bbox[i]
            cat = i + 1
            s = b.south_lat
            n = b.north_lat
            w = b.west_lon
            e = b.east_lon
            x = (w + e) / 2
            y = (s + n) / 2
            line = f"L 5 1\n{w} {s}\n{w} {n}\n{e} {n}\n{e} {s}\n{w} {s}\n1 {cat}\n"
            # XXX: these two lines don't work probably because areas overlap?
            # line = (
            #    f"B 5 1\n{w} {s}\n{w} {n}\n{e} {n}\n{e} {s}\n{w} {s}\n"
            #    f"1 {cat}\nC 1 1\n{x} {y}\n1 {cat}\n"
            # )
            # line = (
            #    f"B 5\n{w} {s}\n{w} {n}\n{e} {n}\n{e} {s}\n{w} {s}\n"
            #    f"C 1 1\n{x} {y}\n1 {cat}\n"
            # )
            line = line.encode()
            p.stdin.write(line)
        p.stdin.close()
        p.wait()

        if p.returncode != 0:
            grass.fatal(_("Error creating output vector map %s") % bbox_map)

        grass.run_command("v.db.addtable",
                          map=bbox_map,
                          columns="srid text, name text")
        for i in range(0, nbbox):
            message("\b" * 80 + _("Populating table...") + f" {i+1}/{nbbox}",
                    "")
            b = bbox[i]
            srid = f"{b.crs_auth_name}:{b.crs_code}"
            cat = i + 1
            grass.run_command(
                "db.execute",
                sql=(f"UPDATE {bbox_map} "
                     f"SET srid='{srid}', "
                     f"""name='{b.crs_name.replace("'", "''")}' """
                     f"WHERE cat={cat}"),
            )
        message()