Example #1
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)
Example #2
0
def main():
    options, unused = gscript.parser()
    input = options['input']
    red = options['red']
    green = options['green']
    blue = options['blue']

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

    expressions = []
    maps = []
    if red:
        expressions.append('%s = r#${input}' % red)
        maps.append(red)
    if green:
        expressions.append('%s = g#${input}' % green)
        maps.append(green)
    if blue:
        expressions.append('%s = b#${input}' % blue)
        maps.append(blue)
    expr = ';'.join(expressions)
    gscript.mapcalc(expr, input=input)

    for name in maps:
        gscript.run_command('r.colors', map=name, color='grey255')
        gscript.raster_history(name)
Example #3
0
 def _import_file(self, filename, module, args):
     mapname = self._map_name(filename)
     gs.message(_('Processing <{}>...').format(mapname))
     if module == 'r.import':
         args['resolution_value'] = self._raster_resolution(filename)
     try:
         gs.run_command(module, input=filename, output=mapname, **args)
         gs.raster_history(mapname)
     except CalledModuleError as e:
         pass  # error already printed
Example #4
0
def main():
    name = options['output']
    type = options['type']
    dip = float(options['dip'])
    az = float(options['azimuth'])
    ea = float(options['easting'])
    no = float(options['northing'])
    el = float(options['elevation'])

    # reg = gscript.region()

    ### test input values ###
    if abs(dip) >= 90:
        gscript.fatal(_("dip must be between -90 and 90."))

    if az < 0 or az >= 360:
        gscript.fatal(_("azimuth must be between 0 and 360"))

    # now the actual algorithm
    az_r = math.radians(-az)
    sinaz = math.sin(az_r)
    cosaz = math.cos(az_r)

    dip_r = math.radians(-dip)
    tandip = math.tan(dip_r)

    kx = sinaz * tandip
    ky = cosaz * tandip
    kz = el - ea * sinaz * tandip - no * cosaz * tandip

    if type == "CELL":
        round = "round"
        dtype = "int"
    elif type == "FCELL":
        round = ""
        dtype = "float"
    else:
        round = ""
        dtype = "double"

    gscript.mapcalc("$name = $type($round(x() * $kx + y() * $ky + $kz))",
                    name=name, type=dtype, round=round, kx=kx, ky=ky, kz=kz)

    gscript.run_command('r.support', map=name, history='')
    gscript.raster_history(name)

    gscript.message(_("Done."))
    t = string.Template("Raster map <$name> generated by r.plane "
                        "at point $ea E, $no N, elevation $el with dip = $dip"
                        " degrees and aspect = $az degrees ccw from north.")
    gscript.message(t.substitute(name=name, ea=ea, no=no, el=el, dip=dip,
                                 az=az))
Example #5
0
def main():
    name = options['output']
    type = options['type']
    dip = float(options['dip'])
    az = float(options['azimuth'])
    ea = float(options['easting'])
    no = float(options['northing'])
    el = float(options['elevation'])

    # reg = gscript.region()

    ### test input values ###
    if abs(dip) >= 90:
        gscript.fatal(_("dip must be between -90 and 90."))

    if az < 0 or az >= 360:
        gscript.fatal(_("azimuth must be between 0 and 360"))

    # now the actual algorithm
    az_r = math.radians(-az)
    sinaz = math.sin(az_r)
    cosaz = math.cos(az_r)

    dip_r = math.radians(-dip)
    tandip = math.tan(dip_r)

    kx = sinaz * tandip
    ky = cosaz * tandip
    kz = el - ea * sinaz * tandip - no * cosaz * tandip

    if type == "CELL":
        round = "round"
        dtype = "int"
    elif type == "FCELL":
        round = ""
        dtype = "float"
    else:
        round = ""
        dtype = "double"

    gscript.mapcalc("$name = $type($round(x() * $kx + y() * $ky + $kz))",
                    name=name, type=dtype, round=round, kx=kx, ky=ky, kz=kz)

    gscript.run_command('r.support', map=name, history='')
    gscript.raster_history(name)

    gscript.message(_("Done."))
    t = string.Template("Raster map <$name> generated by r.plane "
                        "at point $ea E, $no N, elevation $el with dip = $dip"
                        " degrees and aspect = $az degrees ccw from north.")
    gscript.message(t.substitute(name=name, ea=ea, no=no, el=el, dip=dip,
                                 az=az))
Example #6
0
def main():
    global temp_dist, temp_val

    input = options['input']
    output = options['output']
    radius = float(options['radius'])
    metric = options['metric']
    old = options['old']
    new = options['new']
    mapunits = flags['m']

    tmp = str(os.getpid())

    temp_dist = "r.grow.tmp.%s.dist" % tmp

    if new == '':
        temp_val = "r.grow.tmp.%s.val" % tmp
        new = temp_val
    else:
        temp_val = None

    if old == '':
        old = input

    if not mapunits:
        kv = grass.region()
        scale = math.sqrt(float(kv['nsres']) * float(kv['ewres']))
        radius *= scale

    if metric == 'euclidean':
        metric = 'squared'
        radius = radius * radius

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

    try:
        grass.run_command('r.grow.distance', input=input, metric=metric,
                          distance=temp_dist, value=temp_val)
    except CalledModuleError:
        grass.fatal(_("Growing failed. Removing temporary maps."))

    grass.mapcalc(
        "$output = if(!isnull($input),$old,if($dist < $radius,$new,null()))",
        output=output, input=input, radius=radius,
        old=old, new=new, dist=temp_dist)

    grass.run_command('r.colors', map=output, raster=input)

    # write cmd history:
    grass.raster_history(output)
Example #7
0
    def __import_file(self, filename, module, args):
        mapname = os.path.splitext(os.path.basename(filename))[0]

        gs.message(_('Processing <{}>...').format(mapname))

        if module == 'r.import':
            args['resolution_value'] = self.__raster_resolution(filename)

        try:
            gs.run_command(module, input=filename, output=mapname, **args)
            gs.raster_history(mapname)

        except CalledModuleError as e:
            pass
Example #8
0
def main():
    red = options["red"]
    green = options["green"]
    blue = options["blue"]
    brightness = options["strength"]
    full = flags["f"]
    preserve = flags["p"]
    reset = flags["r"]

    # 90 or 98? MAX value controls brightness
    # think of percent (0-100), must be positive or 0
    # must be more than "2" ?

    if full:
        for i in [red, green, blue]:
            grass.run_command("r.colors", map=i, color="grey")
        sys.exit(0)

    if reset:
        for i in [red, green, blue]:
            grass.run_command("r.colors", map=i, color="grey255")
        sys.exit(0)

    if not preserve:
        for i in [red, green, blue]:
            grass.message(_("Processing <%s>...") % i)
            v0 = get_percentile(i, 2)
            v1 = get_percentile(i, brightness)
            grass.debug("<%s>:  min=%f   max=%f" % (i, v0, v1))
            set_colors(i, v0, v1)
    else:
        all_max = 0
        all_min = 999999
        for i in [red, green, blue]:
            grass.message(_("Processing <%s>...") % i)
            v0 = get_percentile(i, 2)
            v1 = get_percentile(i, brightness)
            grass.debug("<%s>:  min=%f   max=%f" % (i, v0, v1))
            all_min = min(all_min, v0)
            all_max = max(all_max, v1)
        grass.debug("all_min=%f   all_max=%f" % (all_min, all_max))
        for i in [red, green, blue]:
            set_colors(i, v0, v1)

        # write cmd history:
    mapset = grass.gisenv()["MAPSET"]
    for i in [red, green, blue]:
        if grass.find_file(i)["mapset"] == mapset:
            grass.raster_history(i)
Example #9
0
def main():
    name = options["output"]
    type = options["type"]
    dip = float(options["dip"])
    az = float(options["azimuth"])
    ea = float(options["easting"])
    no = float(options["northing"])
    el = float(options["elevation"])

    reg = grass.region()

    ### test input values ###
    if abs(dip) >= 90:
        grass.fatal(_("dip must be between -90 and 90."))

    if az < 0 or az >= 360:
        grass.fatal(_("azimuth must be between 0 and 360"))

        ### now the actual algorithm
    az_r = math.radians(-az)
    sinaz = math.sin(az_r)
    cosaz = math.cos(az_r)

    dip_r = math.radians(-dip)
    tandip = math.tan(dip_r)

    kx = sinaz * tandip
    ky = cosaz * tandip
    kz = el - ea * sinaz * tandip - no * cosaz * tandip

    if type == "int":
        round = "round"
    else:
        round = ""

    grass.mapcalc(
        "$name = $type($round(x() * $kx + y() * $ky + $kz))", name=name, type=type, round=round, kx=kx, ky=ky, kz=kz
    )

    grass.raster_history(name)

    grass.message(_("Done."))
    t = string.Template(
        "Raster map <$name> generated by r.plane "
        + "at point $ea E, $no N, elevation $el with dip = $dip degrees and "
        + "aspect = $az degrees ccw from north."
    )
    grass.message(t.substitute(name=name, ea=ea, no=no, el=el, dip=dip, az=az))
 def _import_file(self, filename, module, args):
     mapname = self._map_name(filename)
     gs.message(_('Processing <{}>...').format(mapname))
     if module == 'r.import':
         args['resolution_value'] = self._raster_resolution(filename)
     try:
         gs.run_command(module, input=filename, output=mapname, **args)
         if gs.raster_info(mapname)['datatype'] in ('FCELL', 'DCELL'):
             gs.message('Rounding to integer after reprojection')
             gs.use_temp_region()
             gs.run_command('g.region', raster=mapname)
             gs.run_command('r.mapcalc', quiet=True, expression='tmp_%s = round(%s)' % (mapname, mapname))
             gs.run_command('g.rename', quiet=True, overwrite=True, raster='tmp_%s,%s' % (mapname, mapname))
             gs.del_temp_region()
         gs.raster_history(mapname)
     except CalledModuleError as e:
         pass # error already printed
Example #11
0
def main():
    input = options['input']
    output = options['output_prefix']

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

    if not output:
	output = input

    expr = ';'.join(["${output}.r = r#${input}",
		     "${output}.g = g#${input}",
		     "${output}.b = b#${input}"])
    grass.mapcalc(expr, input = input, output = output)

    for ch in ['r', 'g', 'b']:
	name = "%s.%s" % (output, ch)
	grass.run_command('r.colors', map = name, color = 'grey255')
	grass.raster_history(name)
Example #12
0
def main():
    input = options['input']
    output = options['output_prefix']

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

    if not output:
	output = input.split('@')[0]

    expr = ';'.join(["${output}.r = r#${input}",
		     "${output}.g = g#${input}",
		     "${output}.b = b#${input}"])
    grass.mapcalc(expr, input = input, output = output)

    for ch in ['r', 'g', 'b']:
	name = "%s.%s" % (output, ch)
	grass.run_command('r.colors', map = name, color = 'grey255')
	grass.raster_history(name)
Example #13
0
def import_aster(proj, srcfile, tempfile, band):
    #run gdalwarp with selected options (must be in $PATH)
    #to translate aster image to geotiff
    grass.message(_("Georeferencing aster image ..."))
    grass.debug("gdalwarp -t_srs %s %s %s" % (proj, srcfile, tempfile))

    if platform.system() == "Darwin":
        cmd = ["arch", "-i386", "gdalwarp", "-t_srs", proj, srcfile, tempfile ]
    else:
        cmd = ["gdalwarp", "-t_srs", proj, srcfile, tempfile ]
    p = grass.call(cmd)
    if p != 0:
        #check to see if gdalwarp executed properly
        return

    #import geotiff to GRASS
    grass.message(_("Importing into GRASS ..."))
    outfile = "%s.%s" % (output, band)
    grass.run_command("r.in.gdal", input = tempfile, output = outfile)

    # write cmd history
    grass.raster_history(outfile)
Example #14
0
def import_aster(proj, srcfile, tempfile, band):
    #run gdalwarp with selected options (must be in $PATH)
    #to translate aster image to geotiff
    grass.message(_("Georeferencing aster image ..."))
    grass.debug("gdalwarp -t_srs %s %s %s" % (proj, srcfile, tempfile))

    if platform.system() == "Darwin":
        cmd = ["arch", "-i386", "gdalwarp", "-t_srs", proj, srcfile, tempfile]
    else:
        cmd = ["gdalwarp", "-t_srs", proj, srcfile, tempfile]
    p = grass.call(cmd)
    if p != 0:
        #check to see if gdalwarp executed properly
        return

    #import geotiff to GRASS
    grass.message(_("Importing into GRASS ..."))
    outfile = "%s.%s" % (output, band)
    grass.run_command("r.in.gdal", input=tempfile, output=outfile)

    # write cmd history
    grass.raster_history(outfile)
Example #15
0
def main():
    images = options['input'].split(',')
    output = options['output']

    count = len(images)

    grass.warning(
        _('Do not forget to set region properly to cover all images.'))

    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

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

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

    #modify the color table:
    p = grass.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()

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

    # write cmd history:
    grass.raster_history(output)
Example #16
0
def main():
    global usermask, mapset, tmp_rmaps, tmp_vmaps

    input = options['input']
    output = options['output']
    tension = options['tension']
    smooth = options['smooth']
    method = options['method']
    edge = int(options['edge'])
    segmax = int(options['segmax'])
    npmin = int(options['npmin'])
    lambda_ = float(options['lambda'])
    memory = options['memory']
    quiet = True  # FIXME
    mapset = grass.gisenv()['MAPSET']
    unique = str(os.getpid())  # Shouldn't we use temp name?
    prefix = 'r_fillnulls_%s_' % unique
    failed_list = list(
    )  # a list of failed holes. Caused by issues with v.surf.rst. Connected with #1813

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

    # save original region
    reg_org = grass.region()

    # check if a MASK is already present
    # and remove it to not interfere with NULL lookup part
    # as we don't fill MASKed parts!
    if grass.find_file('MASK', mapset=mapset)['file']:
        usermask = "usermask_mask." + unique
        grass.message(_("A user raster mask (MASK) is present. Saving it..."))
        grass.run_command('g.rename', quiet=quiet, raster=('MASK', usermask))

    # check if method is rst to use v.surf.rst
    if method == 'rst':
        # idea: filter all NULLS and grow that area(s) by 3 pixel, then
        # interpolate from these surrounding 3 pixel edge
        filling = prefix + 'filled'

        grass.use_temp_region()
        grass.run_command('g.region', align=input, quiet=quiet)
        region = grass.region()
        ns_res = region['nsres']
        ew_res = region['ewres']

        grass.message(_("Using RST interpolation..."))
        grass.message(_("Locating and isolating NULL areas..."))

        # creating binary (0/1) map
        if usermask:
            grass.message(_("Skipping masked raster parts"))
            grass.mapcalc(
                "$tmp1 = if(isnull(\"$input\") && !($mask == 0 || isnull($mask)),1,null())",
                tmp1=prefix + 'nulls',
                input=input,
                mask=usermask)
        else:
            grass.mapcalc("$tmp1 = if(isnull(\"$input\"),1,null())",
                          tmp1=prefix + 'nulls',
                          input=input)
        tmp_rmaps.append(prefix + 'nulls')

        # restoring user's mask, if present
        # to ignore MASKed original values
        if usermask:
            grass.message(_("Restoring user mask (MASK)..."))
            try:
                grass.run_command('g.rename',
                                  quiet=quiet,
                                  raster=(usermask, 'MASK'))
            except CalledModuleError:
                grass.warning(_("Failed to restore user MASK!"))
            usermask = None

        # grow identified holes by X pixels
        grass.message(_("Growing NULL areas"))
        tmp_rmaps.append(prefix + 'grown')
        try:
            grass.run_command('r.grow',
                              input=prefix + 'nulls',
                              radius=edge + 0.01,
                              old=1,
                              new=1,
                              out=prefix + 'grown',
                              quiet=quiet)
        except CalledModuleError:
            grass.fatal(
                _("abandoned. Removing temporary map, restoring "
                  "user mask if needed:"))

        # assign unique IDs to each hole or hole system (holes closer than edge distance)
        grass.message(_("Assigning IDs to NULL areas"))
        tmp_rmaps.append(prefix + 'clumped')
        try:
            grass.run_command('r.clump',
                              input=prefix + 'grown',
                              output=prefix + 'clumped',
                              quiet=quiet)
        except CalledModuleError:
            grass.fatal(
                _("abandoned. Removing temporary map, restoring "
                  "user mask if needed:"))

        # get a list of unique hole cat's
        grass.mapcalc("$out = if(isnull($inp), null(), $clumped)",
                      out=prefix + 'holes',
                      inp=prefix + 'nulls',
                      clumped=prefix + 'clumped')
        tmp_rmaps.append(prefix + 'holes')

        # use new IDs to identify holes
        try:
            grass.run_command('r.to.vect',
                              flags='v',
                              input=prefix + 'holes',
                              output=prefix + 'holes',
                              type='area',
                              quiet=quiet)
        except:
            grass.fatal(
                _("abandoned. Removing temporary maps, restoring "
                  "user mask if needed:"))
        tmp_vmaps.append(prefix + 'holes')

        # get a list of unique hole cat's
        cats_file_name = grass.tempfile(False)
        grass.run_command('v.db.select',
                          flags='c',
                          map=prefix + 'holes',
                          columns='cat',
                          file=cats_file_name,
                          quiet=quiet)
        cat_list = list()
        cats_file = open(cats_file_name)
        for line in cats_file:
            cat_list.append(line.rstrip('\n'))
        cats_file.close()
        os.remove(cats_file_name)

        if len(cat_list) < 1:
            grass.fatal(_("Input map has no holes. Check region settings."))

        # GTC Hole is NULL area in a raster map
        grass.message(_("Processing %d map holes") % len(cat_list))
        first = True
        hole_n = 1
        for cat in cat_list:
            holename = prefix + 'hole_' + cat
            # GTC Hole is a NULL area in a raster map
            grass.message(_("Filling hole %s of %s") % (hole_n, len(cat_list)))
            hole_n = hole_n + 1
            # cut out only CAT hole for processing
            try:
                grass.run_command('v.extract',
                                  input=prefix + 'holes',
                                  output=holename + '_pol',
                                  cats=cat,
                                  quiet=quiet)
            except CalledModuleError:
                grass.fatal(
                    _("abandoned. Removing temporary maps, restoring "
                      "user mask if needed:"))
            tmp_vmaps.append(holename + '_pol')

            # zoom to specific hole with a buffer of two cells around the hole to
            # remove rest of data
            try:
                grass.run_command('g.region',
                                  vector=holename + '_pol',
                                  align=input,
                                  w='w-%d' % (edge * 2 * ew_res),
                                  e='e+%d' % (edge * 2 * ew_res),
                                  n='n+%d' % (edge * 2 * ns_res),
                                  s='s-%d' % (edge * 2 * ns_res),
                                  quiet=quiet)
            except CalledModuleError:
                grass.fatal(
                    _("abandoned. Removing temporary maps, restoring "
                      "user mask if needed:"))

            # remove temporary map to not overfill disk
            try:
                grass.run_command('g.remove',
                                  flags='fb',
                                  type='vector',
                                  name=holename + '_pol',
                                  quiet=quiet)
            except CalledModuleError:
                grass.fatal(
                    _("abandoned. Removing temporary maps, restoring "
                      "user mask if needed:"))
            tmp_vmaps.remove(holename + '_pol')

            # copy only data around hole
            grass.mapcalc("$out = if($inp == $catn, $inp, null())",
                          out=holename,
                          inp=prefix + 'holes',
                          catn=cat)
            tmp_rmaps.append(holename)

            # If here loop is split into two, next part of loop can be run in parallel
            # (except final result patching)
            # Downside - on large maps such approach causes large disk usage

            # grow hole border to get it's edge area
            tmp_rmaps.append(holename + '_grown')
            try:
                grass.run_command('r.grow',
                                  input=holename,
                                  radius=edge + 0.01,
                                  old=-1,
                                  out=holename + '_grown',
                                  quiet=quiet)
            except CalledModuleError:
                grass.fatal(
                    _("abandoned. Removing temporary map, restoring "
                      "user mask if needed:"))

            # no idea why r.grow old=-1 doesn't replace existing values with NULL
            grass.mapcalc("$out = if($inp == -1, null(), \"$dem\")",
                          out=holename + '_edges',
                          inp=holename + '_grown',
                          dem=input)
            tmp_rmaps.append(holename + '_edges')

            # convert to points for interpolation
            tmp_vmaps.append(holename)
            try:
                grass.run_command('r.to.vect',
                                  input=holename + '_edges',
                                  output=holename,
                                  type='point',
                                  flags='z',
                                  quiet=quiet)
            except CalledModuleError:
                grass.fatal(
                    _("abandoned. Removing temporary maps, restoring "
                      "user mask if needed:"))

            # count number of points to control segmax parameter for interpolation:
            pointsnumber = grass.vector_info_topo(map=holename)['points']
            grass.verbose(_("Interpolating %d points") % pointsnumber)

            if pointsnumber < 2:
                grass.verbose(_("No points to interpolate"))
                failed_list.append(holename)
                continue

            # Avoid v.surf.rst warnings
            if pointsnumber < segmax:
                use_npmin = pointsnumber
                use_segmax = pointsnumber * 2
            else:
                use_npmin = npmin
                use_segmax = segmax

            # launch v.surf.rst
            tmp_rmaps.append(holename + '_dem')
            try:
                grass.run_command('v.surf.rst',
                                  quiet=quiet,
                                  input=holename,
                                  elev=holename + '_dem',
                                  tension=tension,
                                  smooth=smooth,
                                  segmax=use_segmax,
                                  npmin=use_npmin)
            except CalledModuleError:
                # GTC Hole is NULL area in a raster map
                grass.fatal(_("Failed to fill hole %s") % cat)

            # v.surf.rst sometimes fails with exit code 0
            # related bug #1813
            if not grass.find_file(holename + '_dem')['file']:
                try:
                    tmp_rmaps.remove(holename)
                    tmp_rmaps.remove(holename + '_grown')
                    tmp_rmaps.remove(holename + '_edges')
                    tmp_rmaps.remove(holename + '_dem')
                    tmp_vmaps.remove(holename)
                except:
                    pass
                grass.warning(
                    _("Filling has failed silently. Leaving temporary maps "
                      "with prefix <%s> for debugging.") % holename)
                failed_list.append(holename)
                continue

            # append hole result to interpolated version later used to patch into original DEM
            if first:
                tmp_rmaps.append(filling)
                grass.run_command('g.region',
                                  align=input,
                                  raster=holename + '_dem',
                                  quiet=quiet)
                grass.mapcalc("$out = if(isnull($inp), null(), $dem)",
                              out=filling,
                              inp=holename,
                              dem=holename + '_dem')
                first = False
            else:
                tmp_rmaps.append(filling + '_tmp')
                grass.run_command('g.region',
                                  align=input,
                                  raster=(filling, holename + '_dem'),
                                  quiet=quiet)
                grass.mapcalc(
                    "$out = if(isnull($inp), if(isnull($fill), null(), $fill), $dem)",
                    out=filling + '_tmp',
                    inp=holename,
                    dem=holename + '_dem',
                    fill=filling)
                try:
                    grass.run_command('g.rename',
                                      raster=(filling + '_tmp', filling),
                                      overwrite=True,
                                      quiet=quiet)
                except CalledModuleError:
                    grass.fatal(
                        _("abandoned. Removing temporary maps, restoring user "
                          "mask if needed:"))
                # this map has been removed. No need for later cleanup.
                tmp_rmaps.remove(filling + '_tmp')

            # remove temporary maps to not overfill disk
            try:
                tmp_rmaps.remove(holename)
                tmp_rmaps.remove(holename + '_grown')
                tmp_rmaps.remove(holename + '_edges')
                tmp_rmaps.remove(holename + '_dem')
            except:
                pass
            try:
                grass.run_command('g.remove',
                                  quiet=quiet,
                                  flags='fb',
                                  type='raster',
                                  name=(holename, holename + '_grown',
                                        holename + '_edges',
                                        holename + '_dem'))
            except CalledModuleError:
                grass.fatal(
                    _("abandoned. Removing temporary maps, restoring "
                      "user mask if needed:"))
            try:
                tmp_vmaps.remove(holename)
            except:
                pass
            try:
                grass.run_command('g.remove',
                                  quiet=quiet,
                                  flags='fb',
                                  type='vector',
                                  name=holename)
            except CalledModuleError:
                grass.fatal(
                    _("abandoned. Removing temporary maps, restoring user mask if needed:"
                      ))

    # check if method is different from rst to use r.resamp.bspline
    if method != 'rst':
        grass.message(_("Using %s bspline interpolation") % method)

        # clone current region
        grass.use_temp_region()
        grass.run_command('g.region', align=input)

        reg = grass.region()
        # launch r.resamp.bspline
        tmp_rmaps.append(prefix + 'filled')
        # If there are no NULL cells, r.resamp.bslpine call
        # will end with an error although for our needs it's fine
        # Only problem - this state must be read from stderr
        new_env = dict(os.environ)
        new_env['LC_ALL'] = 'C'
        if usermask:
            try:
                p = grass.core.start_command('r.resamp.bspline',
                                             input=input,
                                             mask=usermask,
                                             output=prefix + 'filled',
                                             method=method,
                                             ew_step=3 * reg['ewres'],
                                             ns_step=3 * reg['nsres'],
                                             lambda_=lambda_,
                                             memory=memory,
                                             flags='n',
                                             stderr=subprocess.PIPE,
                                             env=new_env)
                stderr = grass.decode(p.communicate()[1])
                if "No NULL cells found" in stderr:
                    grass.run_command('g.copy',
                                      raster='%s,%sfilled' % (input, prefix),
                                      overwrite=True)
                    p.returncode = 0
                    grass.warning(
                        _("Input map <%s> has no holes. Copying to output without modification."
                          ) % (input, ))
            except CalledModuleError as e:
                grass.fatal(
                    _("Failure during bspline interpolation. Error message: %s"
                      ) % stderr)
        else:
            try:
                p = grass.core.start_command('r.resamp.bspline',
                                             input=input,
                                             output=prefix + 'filled',
                                             method=method,
                                             ew_step=3 * reg['ewres'],
                                             ns_step=3 * reg['nsres'],
                                             lambda_=lambda_,
                                             memory=memory,
                                             flags='n',
                                             stderr=subprocess.PIPE,
                                             env=new_env)
                stderr = grass.decode(p.communicate()[1])
                if "No NULL cells found" in stderr:
                    grass.run_command('g.copy',
                                      raster='%s,%sfilled' % (input, prefix),
                                      overwrite=True)
                    p.returncode = 0
                    grass.warning(
                        _("Input map <%s> has no holes. Copying to output without modification."
                          ) % (input, ))
            except CalledModuleError as e:
                grass.fatal(
                    _("Failure during bspline interpolation. Error message: %s"
                      ) % stderr)

    # restoring user's mask, if present:
    if usermask:
        grass.message(_("Restoring user mask (MASK)..."))
        try:
            grass.run_command('g.rename',
                              quiet=quiet,
                              raster=(usermask, 'MASK'))
        except CalledModuleError:
            grass.warning(_("Failed to restore user MASK!"))
        usermask = None

    # set region to original extents, align to input
    grass.run_command('g.region',
                      n=reg_org['n'],
                      s=reg_org['s'],
                      e=reg_org['e'],
                      w=reg_org['w'],
                      align=input)

    # patch orig and fill map
    grass.message(_("Patching fill data into NULL areas..."))
    # we can use --o here as g.parser already checks on startup
    grass.run_command('r.patch',
                      input=(input, prefix + 'filled'),
                      output=output,
                      overwrite=True)

    # restore the real region
    grass.del_temp_region()

    grass.message(_("Filled raster map is: %s") % output)

    # write cmd history:
    grass.raster_history(output)

    if len(failed_list) > 0:
        grass.warning(
            _("Following holes where not filled. Temporary maps with are left "
              "in place to allow examination of unfilled holes"))
        outlist = failed_list[0]
        for hole in failed_list[1:]:
            outlist = ', ' + outlist
        grass.message(outlist)

    grass.message(_("Done."))
Example #17
0
def main():
    if not hasNumPy:
        grass.fatal(_("Required dependency NumPy not found. Exiting."))

    sharpen = options['method']  # sharpening algorithm
    ms1 = options['blue']  # blue channel
    ms2 = options['green']  # green channel
    ms3 = options['red']  # red channel
    pan = options['pan']  # high res pan channel
    out = options['output']  # prefix for output RGB maps
    bladjust = flags['l']  # adjust blue channel
    sproc = flags['s']  # serial processing

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

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

    grass.message(_("Performing pan sharpening with hi res pan image: %f" % panres))

    if sharpen == "brovey":
        grass.verbose(_("Using Brovey algorithm"))

        # pan/intensity histogram matching using linear regression
        outname = 'tmp%s_pan1' % pid
        panmatch1 = matchhist(pan, ms1, outname)

        outname = 'tmp%s_pan2' % pid
        panmatch2 = matchhist(pan, ms2, outname)

        outname = 'tmp%s_pan3' % pid
        panmatch3 = matchhist(pan, ms3, outname)

        outr = '%s_red' % out
        outg = '%s_green' % out
        outb = '%s_blue' % out

        # calculate brovey transformation
        grass.message(_("Calculating Brovey transformation..."))

        if sproc:
            # serial processing
            e = '''eval(k = "$ms1" + "$ms2" + "$ms3")
                "$outr" = 1.0 * "$ms3" * "$panmatch3" / k
                "$outg" = 1.0 * "$ms2" * "$panmatch2" / k
                "$outb" = 1.0 * "$ms1" * "$panmatch1" / k'''
            grass.mapcalc(e, outr=outr, outg=outg, outb=outb,
                          panmatch1=panmatch1, panmatch2=panmatch2,
                          panmatch3=panmatch3, ms1=ms1, ms2=ms2, ms3=ms3,
                          overwrite=True)
        else:
            # parallel processing
            pb = grass.mapcalc_start('%s_blue = (1.0 * %s * %s) / (%s + %s + %s)' %
                                     (out, ms1, panmatch1, ms1, ms2, ms3),
                                     overwrite=True)
            pg = grass.mapcalc_start('%s_green = (1.0 * %s * %s) / (%s + %s + %s)' %
                                     (out, ms2, panmatch2, ms1, ms2, ms3),
                                     overwrite=True)
            pr = grass.mapcalc_start('%s_red = (1.0 * %s * %s) / (%s + %s + %s)' %
                                     (out, ms3, panmatch3, ms1, ms2, ms3),
                                     overwrite=True)

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

        # Cleanup
        grass.run_command('g.remove', flags='f', quiet=True, type='raster',
                          name='%s,%s,%s' % (panmatch1, panmatch2, panmatch3))

    elif sharpen == "ihs":
        grass.verbose(_("Using IHS<->RGB algorithm"))
        # transform RGB channels into IHS color space
        grass.message(_("Transforming to IHS color space..."))
        grass.run_command('i.rgb.his', overwrite=True,
                          red=ms3,
                          green=ms2,
                          blue=ms1,
                          hue="tmp%s_hue" % pid,
                          intensity="tmp%s_int" % pid,
                          saturation="tmp%s_sat" % pid)

        # pan/intensity histogram matching using linear regression
        target = "tmp%s_int" % pid
        outname = "tmp%s_pan_int" % pid
        panmatch = matchhist(pan, target, outname)

        # substitute pan for intensity channel and transform back to RGB color space
        grass.message(_("Transforming back to RGB color space and sharpening..."))
        grass.run_command('i.his.rgb', overwrite=True,
                          hue="tmp%s_hue" % pid,
                          intensity="%s" % panmatch,
                          saturation="tmp%s_sat" % pid,
                          red="%s_red" % out,
                          green="%s_green" % out,
                          blue="%s_blue" % out)

        # Cleanup
        grass.run_command('g.remove', flags='f', quiet=True, type='raster',
                          name=panmatch)

    elif sharpen == "pca":
        grass.verbose(_("Using PCA/inverse PCA algorithm"))
        grass.message(_("Creating PCA images and calculating eigenvectors..."))

        # initial PCA with RGB channels
        pca_out = grass.read_command('i.pca', quiet=True, rescale='0,0',
                                     input='%s,%s,%s' % (ms1, ms2, ms3),
                                     output='tmp%s.pca' % pid)
        if len(pca_out) < 1:
            grass.fatal(_("Input has no data. Check region settings."))

        b1evect = []
        b2evect = []
        b3evect = []
        for l in pca_out.replace('(', ',').replace(')', ',').splitlines():
            b1evect.append(float(l.split(',')[1]))
            b2evect.append(float(l.split(',')[2]))
            b3evect.append(float(l.split(',')[3]))

        # inverse PCA with hi res pan channel substituted for principal component 1
        pca1 = 'tmp%s.pca.1' % pid
        pca2 = 'tmp%s.pca.2' % pid
        pca3 = 'tmp%s.pca.3' % pid
        b1evect1 = b1evect[0]
        b1evect2 = b1evect[1]
        b1evect3 = b1evect[2]
        b2evect1 = b2evect[0]
        b2evect2 = b2evect[1]
        b2evect3 = b2evect[2]
        b3evect1 = b3evect[0]
        b3evect2 = b3evect[1]
        b3evect3 = b3evect[2]

        outname = 'tmp%s_pan' % pid
        panmatch = matchhist(pan, ms1, outname)

        grass.message(_("Performing inverse PCA ..."))

        stats1 = grass.parse_command("r.univar", map=ms1, flags='g',
                                     parse=(grass.parse_key_val,
                                            {'sep': '='}))
        stats2 = grass.parse_command("r.univar", map=ms2, flags='g',
                                     parse=(grass.parse_key_val,
                                            {'sep': '='}))
        stats3 = grass.parse_command("r.univar", map=ms3, flags='g',
                                     parse=(grass.parse_key_val,
                                            {'sep': '='}))

        b1mean = float(stats1['mean'])
        b2mean = float(stats2['mean'])
        b3mean = float(stats3['mean'])

        if sproc:
            # serial processing
            e = '''eval(k = "$ms1" + "$ms2" + "$ms3")
                "$outr" = 1.0 * "$ms3" * "$panmatch3" / k
                "$outg" = 1.0 * "$ms2" * "$panmatch2" / k
                "$outb" = 1.0* "$ms1" * "$panmatch1" / k'''

            outr = '%s_red' % out
            outg = '%s_green' % out
            outb = '%s_blue' % out

            cmd1 = "$outb = (1.0 * $panmatch * $b1evect1) + ($pca2 * $b2evect1) + ($pca3 * $b3evect1) + $b1mean"
            cmd2 = "$outg = (1.0 * $panmatch * $b1evect2) + ($pca2 * $b2evect1) + ($pca3 * $b3evect2) + $b2mean"
            cmd3 = "$outr = (1.0 * $panmatch * $b1evect3) + ($pca2 * $b2evect3) + ($pca3 * $b3evect3) + $b3mean"

            cmd = '\n'.join([cmd1, cmd2, cmd3])

            grass.mapcalc(cmd, outb=outb, outg=outg, outr=outr,
                          panmatch=panmatch, pca2=pca2, pca3=pca3,
                          b1evect1=b1evect1, b2evect1=b2evect1, b3evect1=b3evect1,
                          b1evect2=b1evect2, b2evect2=b2evect2, b3evect2=b3evect2,
                          b1evect3=b1evect3, b2evect3=b2evect3, b3evect3=b3evect3,
                          b1mean=b1mean, b2mean=b2mean, b3mean=b3mean,
                          overwrite=True)
        else:
            # parallel processing
            pb = grass.mapcalc_start('%s_blue = (%s * %f) + (%s * %f) + (%s * %f) + %f'
                                     % (out, panmatch, b1evect1, pca2,
                                        b2evect1, pca3, b3evect1, b1mean),
                                     overwrite=True)

            pg = grass.mapcalc_start('%s_green = (%s * %f) + (%s * %f) + (%s * %f) + %f'
                                     % (out, panmatch, b1evect2, pca2,
                                        b2evect2, pca3, b3evect2, b2mean),
                                     overwrite=True)

            pr = grass.mapcalc_start('%s_red = (%s * %f) + (%s * %f) + (%s * ''%f) + %f'
                                     % (out, panmatch, b1evect3, pca2,
                                        b2evect3, pca3, b3evect3, b3mean),
                                     overwrite=True)

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

        # Cleanup
        grass.run_command('g.remove', flags='f', quiet=True, type="raster",
                          pattern='tmp%s*,%s' % (pid, panmatch))

    # 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
    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..."))
        rules = grass.tempfile()
        colors = open(rules, 'w')
        colors.write('5 0 0 0\n20 200 200 200\n40 230 230 230\n67 255 255 255 \n')
        colors.close()

        grass.run_command('r.colors', map="%s_blue" % out, rules=rules)
        os.remove(rules)

    # 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 output
    grass.run_command('i.group', group=out,
                      input="{n}_red,{n}_blue,{n}_green".format(n=out))

    # Cleanup
    grass.run_command('g.remove', flags="f", type="raster",
                      pattern="tmp%s*" % pid, quiet=True)
Example #18
0
def main():

    global nuldev, tmp
    nuldev = open(os.devnull, "w")
    tmp = "v_tin_to_rast_%d" % os.getpid()

    input = options["input"]
    output = options["output"]

    # initialize GRASS library
    G_gisinit("")

    # check if vector map exists
    mapset = G_find_vector2(input, "")
    if not mapset:
        grass.fatal("Vector map <%s> not found" % input)

    # define map structure
    map_info = pointer(Map_info())

    # set vector topology to level 2
    Vect_set_open_level(2)

    # opens the vector map
    Vect_open_old(map_info, input, mapset)

    Vect_maptype_info(map_info, input, mapset)

    # check if vector map is 3D
    if Vect_is_3d(map_info):
        grass.message("Vector map <%s> is 3D" % input)
    else:
        grass.fatal("Vector map <%s> is not 3D" % input)

    # allocation of the output buffer using the values of the current region
    window = pointer(Cell_head())
    G_get_window(window)
    nrows = window.contents.rows
    ncols = window.contents.cols
    xref = window.contents.west
    yref = window.contents.south
    xres = window.contents.ew_res
    yres = window.contents.ns_res

    outrast = []
    for i in range(nrows):
        outrast[i:] = [Rast_allocate_d_buf()]

    # create new raster
    outfd = Rast_open_new(output, DCELL_TYPE)
    if outfd < 0:
        grass.fatal("Impossible to create a raster <%s>" % output)

    # insert null values in cells
    grass.message(_("Step 1/4: Inserting null values in cells..."))
    for i in range(nrows):
        Rast_set_d_null_value(outrast[i], ncols)
        G_percent(i, nrows, 2)

    #####  main work #####
    grass.message(_("Step 2/4: TIN preprocessing..."))
    z = c_double()
    G_percent(0, nrows, 2)
    Vect_tin_get_z(map_info, xref, yref, byref(z), None, None)

    grass.message(_("Step 3/4: Converting TIN to raster..."))
    for i in range(nrows):
        for j in range(ncols):
            x = xref + j * xres
            y = yref + i * yres
            Vect_tin_get_z(map_info, x, y, byref(z), None, None)
            outrast[i][j] = z
        G_percent(i, nrows, 2)

    grass.message(_("Step 4/4: Writing raster map..."))

    for i in range(nrows - 1, -1, -1):
        Rast_put_d_row(outfd, outrast[i])
        G_percent(nrows - i, nrows, 2)

    # clear buffer
    for i in range(nrows):
        G_free(outrast[i])

    # close raster
    Rast_close(outfd)

    # close vector
    Vect_close(map_info)

    # cut output raster to TIN vertical range
    vtop = grass.read_command("v.info", flags="g",
                              map=input).rsplit()[4].split("=")[1]
    vbottom = (grass.read_command("v.info", flags="g",
                                  map=input).rsplit()[5].split("=")[1])

    tmp = "v_tin_to_rast_%d" % os.getpid()
    grass.mapcalc(
        "$tmp = if($vbottom < $output && $output < $vtop, $output, null())",
        tmp=tmp,
        output=output,
        vbottom=vbottom,
        vtop=vtop,
        quiet=True,
        stderr=nuldev,
    )

    grass.parse_command("g.rename",
                        rast=(tmp, output),
                        quiet=True,
                        stderr=nuldev)

    # write cmd history:
    grass.run_command(
        "r.support",
        map=output,
        title="%s" % output,
        history="",
        description="generated by v.tin.to.rast",
    )
    grass.raster_history(output)

    grass.message(_("Done."))
Example #19
0
def main():
    global vrtfile, tmpfile

    infile = options['input']
    rast = options['output']
    also = flags['a']

    #### check for gdalinfo (just to check if installation is complete)
    if not grass.find_program('gdalinfo', '--help'):
        grass.fatal(
            _("'gdalinfo' not found, install GDAL tools first (http://www.gdal.org)"
              ))

    pid = str(os.getpid())
    tmpfile = grass.tempfile()

    ################### let's go

    spotdir = os.path.dirname(infile)
    spotname = grass.basename(infile, 'hdf')

    if rast:
        name = rast
    else:
        name = spotname

    if not grass.overwrite() and grass.find_file(name)['file']:
        grass.fatal(_("<%s> already exists. Aborting.") % name)

    # still a ZIP file?  (is this portable?? see the r.in.srtm script for ideas)
    if infile.lower().endswith('.zip'):
        grass.fatal(_("Please extract %s before import.") % infile)

    try:
        p = grass.Popen(['file', '-ib', infile], stdout=grass.PIPE)
        s = p.communicate()[0]
        if s == "application/x-zip":
            grass.fatal(_("Please extract %s before import.") % infile)
    except:
        pass

    ### create VRT header for NDVI

    projfile = os.path.join(spotdir, "0001_LOG.TXT")
    vrtfile = tmpfile + '.vrt'

    # first process the NDVI:
    grass.try_remove(vrtfile)
    create_VRT_file(projfile, vrtfile, infile)

    ## let's import the NDVI map...
    grass.message(_("Importing SPOT VGT NDVI map..."))
    if grass.run_command('r.in.gdal', input=vrtfile, output=name) != 0:
        grass.fatal(_("An error occurred. Stop."))

    grass.message(_("Imported SPOT VEGETATION NDVI map <%s>.") % name)

    #################
    ## http://www.vgt.vito.be/faq/FAQS/faq19.html
    # What is the relation between the digital number and the real NDVI ?
    # Real NDVI =coefficient a * Digital Number + coefficient b
    #           = a * DN +b
    #
    # Coefficient a = 0.004
    # Coefficient b = -0.1

    # clone current region
    # switch to a temporary region
    grass.use_temp_region()

    grass.run_command('g.region', rast=name, quiet=True)

    grass.message(_("Remapping digital numbers to NDVI..."))
    tmpname = "%s_%s" % (name, pid)
    grass.mapcalc("$tmpname = 0.004 * $name - 0.1", tmpname=tmpname, name=name)
    grass.run_command('g.remove',
                      flags='f',
                      type='rast',
                      pattern=name,
                      quiet=True)
    grass.run_command('g.rename', rast=(tmpname, name), quiet=True)

    # write cmd history:
    grass.raster_history(name)

    #apply color table:
    grass.run_command('r.colors', map=name, color='ndvi', quiet=True)

    ##########################
    # second, optionally process the SM quality map:

    #SM Status Map
    # http://nieuw.vgt.vito.be/faq/FAQS/faq22.html
    #Data about
    # Bit NR 7: Radiometric quality for B0 coded as 0 if bad and 1 if good
    # Bit NR 6: Radiometric quality for B2 coded as 0 if bad and 1 if good
    # Bit NR 5: Radiometric quality for B3 coded as 0 if bad and 1 if good
    # Bit NR 4: Radiometric quality for MIR coded as 0 if bad and 1 if good
    # Bit NR 3: land code 1 or water code 0
    # Bit NR 2: ice/snow code 1 , code 0 if there is no ice/snow
    # Bit NR 1:	0	0	1		1
    # Bit NR 0:	0	1	0		1
    # 		clear	shadow	uncertain	cloud
    #
    #Note:
    # pos 7     6    5    4    3    2   1   0 (bit position)
    #   128    64   32   16    8    4   2   1 (values for 8 bit)
    #
    #
    # Bit 4-7 should be 1: their sum is 240
    # Bit 3   land code, should be 1, sum up to 248 along with higher bits
    # Bit 2   ice/snow code
    # Bit 0-1 should be 0
    #
    # A good map threshold: >= 248

    if also:
        grass.message(_("Importing SPOT VGT NDVI quality map..."))
        grass.try_remove(vrtfile)
        qname = spotname.replace('NDV', 'SM')
        qfile = os.path.join(spotdir, qname)
        create_VRT_file(projfile, vrtfile, qfile)

        ## let's import the SM quality map...
        smfile = name + '.sm'
        if grass.run_command('r.in.gdal', input=vrtfile, output=smfile) != 0:
            grass.fatal(_("An error occurred. Stop."))

        # some of the possible values:
        rules = [
            r + '\n' for r in [
                '8 50 50 50', '11 70 70 70', '12 90 90 90', '60 grey',
                '155 blue', '232 violet', '235 red', '236 brown', '248 orange',
                '251 yellow', '252 green'
            ]
        ]
        grass.write_command('r.colors', map=smfile, rules='-', stdin=rules)

        grass.message(
            _("Imported SPOT VEGETATION SM quality map <%s>.") % smfile)
        grass.message(
            _("Note: A snow map can be extracted by category 252 (d.rast %s cat=252)"
              ) % smfile)
        grass.message("")
        grass.message(_("Filtering NDVI map by Status Map quality layer..."))

        filtfile = "%s_filt" % name
        grass.mapcalc(
            "$filtfile = if($smfile % 4 == 3 || ($smfile / 16) % 16 == 0, null(), $name)",
            filtfile=filtfile,
            smfile=smfile,
            name=name)
        grass.run_command('r.colors', map=filtfile, color='ndvi', quiet=True)
        grass.message(_("Filtered SPOT VEGETATION NDVI map <%s>.") % filtfile)

        # write cmd history:
        grass.raster_history(smfile)
        grass.raster_history(filtfile)

    grass.message(_("Done."))
Example #20
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)
Example #21
0
def main():
    options, flags = grass.parser()

    elevation_input = options['input']
    pca_shade_output = options['output']
    altitude = float(options['altitude'])
    number_of_azimuths = int(options['nazimuths'])
    z_exaggeration = float(options['zscale'])
    scale = float(options['scale'])
    units = options['units']
    shades_basename = options['shades_basename']
    pca_basename = pca_basename_user = options['pca_shades_basename']
    nprocs = int(options['nprocs'])

    full_circle = 360
    # let's use floats here and leave the consequences to the user
    smallest_angle = float(full_circle) / number_of_azimuths
    azimuths = list(frange(0, full_circle, smallest_angle))

    if not shades_basename:
        shades_basename = create_tmp_map_name('shade')
        MREMOVE.append(shades_basename)

    if not pca_basename:
        pca_basename = pca_shade_output + '_pca'
    pca_maps = [
        pca_basename + '.' + str(i) for i in range(1, number_of_azimuths + 1)
    ]
    if not pca_basename_user:
        REMOVE.extend(pca_maps)

    # here we check all the posible
    if not grass.overwrite():
        check_map_names(shades_basename,
                        grass.gisenv()['MAPSET'],
                        suffixes=azimuths)
        check_map_names(pca_basename,
                        grass.gisenv()['MAPSET'],
                        suffixes=range(1, number_of_azimuths))

    grass.info(_("Running r.relief in a loop..."))
    count = 0
    # Parallel processing
    proc_list = []
    proc_count = 0
    suffixes = []
    all_suffixes = []
    core.percent(0, number_of_azimuths, 1)
    for azimuth in azimuths:
        count += 1
        core.percent(count, number_of_azimuths, 10)

        suffix = '_' + str(azimuth)
        proc_list.append(
            Process(target=run_r_shaded_relief,
                    args=(elevation_input, shades_basename, altitude, azimuth,
                          z_exaggeration, scale, units, suffix)))

        proc_list[proc_count].start()
        proc_count += 1
        suffixes.append(suffix)
        all_suffixes.append(suffix)

        if proc_count == nprocs or proc_count == number_of_azimuths \
                or count == number_of_azimuths:
            proc_count = 0
            exitcodes = 0
            for proc in proc_list:
                proc.join()
                exitcodes += proc.exitcode

            if exitcodes != 0:
                core.fatal(_("Error during r.relief computation"))

            # Empty process list
            proc_list = []
            suffixes = []
    # FIXME: how percent really works?
    # core.percent(1, 1, 1)

    shade_maps = [shades_basename + suf for suf in all_suffixes]

    grass.info(_("Running r.pca..."))

    # not quiet=True to get percents
    grass.run_command('i.pca',
                      input=shade_maps,
                      output=pca_basename,
                      overwrite=core.overwrite())

    grass.info(
        _("Creating RGB composite from "
          "PC1 (red), PC2 (green), PC3 (blue) ..."))
    grass.run_command('r.composite',
                      red=pca_maps[0],
                      green=pca_maps[1],
                      blue=pca_maps[2],
                      output=pca_shade_output,
                      overwrite=core.overwrite(),
                      quiet=True)
    grass.raster_history(pca_shade_output)

    if pca_basename_user:
        set_color_table(pca_maps, map_=shade_maps[0])
def main():
    # split input images
    all_images = options['input']
    images = all_images.split(',')
    # number of images
    n_images = len(images)
    # database path
    dbopt = options['database']
    # output suffix
    suffix = options['suffix']
    # output mosaic map
    mosaic = options['output']
    output_names = []
    # name for average table
    table_ave = "t%s_average" % suffix
    # increment of one the maximum value for a correct use of range function
    max_value = int(options['max']) + 1
    # if the db path is the default one
    if dbopt.find('$GISDBASE/$LOCATION_NAME/$MAPSET') == 0:
        dbopt_split = dbopt.split('/')[-1]
        env = grass.gisenv()
        path = os.path.join(env['GISDBASE'], env['LOCATION_NAME'],
                            env['MAPSET'])
        dbpath = os.path.join(path, dbopt_split)
    else:
        if os.access(os.path.dirname(dbopt), os.W_OK):
            path = os.path.dirname(dbopt)
            dbpath = dbopt
        else:
            grass.fatal(
                _("Folder to write database files does not" +
                  " exist or is not writeable"))
    # connect to the db
    db = sqlite3.connect(dbpath)
    curs = db.cursor()
    grass.message(_("Calculating Cumulative Distribution Functions ..."))

    # number of pixels per value, summarized for all images
    numPixelValue = list(range(0, max_value))
    for n in range(0, max_value):
        numPixelValue[n] = 0

    # cumulative histogram for each value and each image
    cumulHistoValue = list(range(0, max_value))

    # set up temp region only once
    grass.use_temp_region()

    # for each image
    for i in images:
        iname = i.split('@')[0]
        # drop table if exist
        query_drop = "DROP TABLE if exists \"t%s\"" % iname
        curs.execute(query_drop)
        # create table
        query_create = "CREATE TABLE \"t%s\" (grey_value integer,pixel_frequency " % iname
        query_create += "integer, cumulative_histogram integer, cdf real)"
        curs.execute(query_create)
        index_create = "CREATE UNIQUE INDEX \"t%s_grey_value\" ON \"t%s\" (grey_value) " % (
            iname, iname)
        curs.execute(index_create)
        # set the region on the raster
        grass.run_command('g.region', raster=i)
        # calculate statistics
        stats_out = grass.pipe_command('r.stats',
                                       flags='cin',
                                       input=i,
                                       separator=':')
        stats = stats_out.communicate()[0].decode('utf-8').split('\n')[:-1]
        stats_dict = dict(s.split(':', 1) for s in stats)
        cdf = 0
        curs.execute("BEGIN")
        # for each number in the range
        for n in range(0, max_value):
            # try to insert the values otherwise insert 0

            try:
                val = int(stats_dict[str(n)])
                cdf += val
                numPixelValue[n] += val
                insert = "INSERT INTO \"t%s\" VALUES (%i, %i, %i, 0.000000)" % (
                    iname, n, val, cdf)
                curs.execute(insert)
            except:
                insert = "INSERT INTO \"t%s\" VALUES (%i, 0, %i, 0.000000)" % (
                    iname, n, cdf)
                curs.execute(insert)
            # save cumulative_histogram for the second loop
            cumulHistoValue[n] = cdf
        curs.execute("COMMIT")
        db.commit()
        # number of pixel is the cdf value
        numPixel = cdf
        # for each number in the range
        # cdf is updated using the number of non-null pixels for the current image
        curs.execute("BEGIN")
        for n in range(0, max_value):
            # select value for cumulative_histogram for the range number
            """
            select_ch = "SELECT cumulative_histogram FROM \"t%s\" WHERE " % iname
            select_ch += "(grey_value=%i)" % n
            result = curs.execute(select_ch)
            val = result.fetchone()[0]
            """
            val = cumulHistoValue[n]
            # update cdf with new value
            if val != 0 and numPixel != 0:
                update_cdf = round(float(val) / float(numPixel), 6)
                update_cdf = "UPDATE \"t%s\" SET cdf=%s WHERE (grey_value=%i)" % (
                    iname, update_cdf, n)
                curs.execute(update_cdf)

        curs.execute("COMMIT")
        db.commit()
    db.commit()
    pixelTot = 0

    # get total number of pixels divided by number of images
    # for each number in the range
    for n in range(0, max_value):
        """
        numPixel = 0
        # for each image
        for i in images:
            iname = i.split('@')[0]
            pixel_freq = "SELECT pixel_frequency FROM \"t%s\" WHERE (grey_value=%i)" % (
                                                                iname, n)
            result = curs.execute(pixel_freq)
            val = result.fetchone()[0]
            numPixel += val
        """
        # calculate number of pixel divide by number of images
        div = (int(numPixelValue[n] / n_images))
        pixelTot += div

    # drop average table
    query_drop = "DROP TABLE if exists %s" % table_ave
    curs.execute(query_drop)
    # create average table
    query_create = "CREATE TABLE %s (grey_value integer,average " % table_ave
    query_create += "integer, cumulative_histogram integer, cdf real)"
    curs.execute(query_create)
    index_create = "CREATE UNIQUE INDEX \"%s_grey_value\" ON \"%s\" (grey_value) " % (
        table_ave, table_ave)
    curs.execute(index_create)
    cHist = 0
    # for each number in the range
    curs.execute("BEGIN")
    for n in range(0, max_value):
        tot = 0
        """
        # for each image
        for i in images:
            iname = i.split('@')[0]
            # select pixel frequency
            pixel_freq = "SELECT pixel_frequency FROM \"t%s\" WHERE (grey_value=%i)" % (
                                                            iname, n)
            result = curs.execute(pixel_freq)
            val = result.fetchone()[0]
            tot += val
        """
        tot = numPixelValue[n]
        # calculate new value of pixel_frequency
        average = (tot / n_images)
        cHist = cHist + int(average)
        # insert new values into average table
        if cHist != 0 and pixelTot != 0:
            cdf = float(cHist) / float(pixelTot)
            insert = "INSERT INTO %s VALUES (%i, %i, %i, %s)" % (
                table_ave, n, int(average), cHist, cdf)
            curs.execute(insert)
    curs.execute("COMMIT")
    db.commit()

    # for each image
    grass.message(_("Reclassifying bands based on average histogram..."))
    for i in images:
        iname = i.split('@')[0]
        grass.run_command('g.region', raster=i)
        # write average rules file
        outfile = open(grass.tempfile(), 'w')
        new_grey = 0
        for n in range(0, max_value):
            select_newgrey = "SELECT b.grey_value FROM \"t%s\" as a, " % iname
            select_newgrey += "%s as b WHERE a.grey_value=%i " % (table_ave, n) \
                + "ORDER BY abs(a.cdf-b.cdf) LIMIT 1"
            # write line with old and new value
            try:
                result_new = curs.execute(select_newgrey)
                new_grey = result_new.fetchone()[0]
                out_line = "%d = %d\n" % (n, new_grey)
                outfile.write(out_line)
            except:
                out_line = "%d = %d\n" % (n, new_grey)
                outfile.write(out_line)

        outfile.close()
        outname = '%s.%s' % (iname, suffix)
        # check if a output map already exists
        result = grass.core.find_file(outname, element='cell')
        if result['fullname'] and grass.overwrite():
            grass.run_command('g.remove',
                              flags='f',
                              type='raster',
                              name=outname)
            grass.run_command('r.reclass',
                              input=i,
                              out=outname,
                              rules=outfile.name)
        elif result['fullname'] and not grass.overwrite():
            grass.warning(
                _("Raster map %s already exists and will not be overwritten" %
                  i))
        else:
            grass.run_command('r.reclass',
                              input=i,
                              out=outname,
                              rules=outfile.name)
        output_names.append(outname)
        # remove the rules file
        grass.try_remove(outfile.name)
        # write cmd history:
        grass.raster_history(outname)
    db.commit()
    db.close()
    if mosaic:
        grass.message(_("Processing mosaic <%s>..." % mosaic))
        grass.run_command('g.region', raster=all_images)
        grass.run_command('r.patch', input=output_names, output=mosaic)
Example #23
0
def main():

    global nuldev, tmp
    nuldev = file(os.devnull, "w")
    tmp = "v_tin_to_rast_%d" % os.getpid()

    input = options["input"]
    output = options["output"]

    # initialize GRASS library
    G_gisinit("")

    # check if vector map exists
    mapset = G_find_vector2(input, "")
    if not mapset:
        grass.fatal("Vector map <%s> not found" % input)

    # define map structure
    map_info = pointer(Map_info())

    # set vector topology to level 2
    Vect_set_open_level(2)

    # opens the vector map
    Vect_open_old(map_info, input, mapset)

    Vect_maptype_info(map_info, input, mapset)

    # check if vector map is 3D
    if Vect_is_3d(map_info):
        grass.message("Vector map <%s> is 3D" % input)
    else:
        grass.fatal("Vector map <%s> is not 3D" % input)

    # allocation of the output buffer using the values of the current region
    window = pointer(Cell_head())
    G_get_window(window)
    nrows = window.contents.rows
    ncols = window.contents.cols
    xref = window.contents.west
    yref = window.contents.south
    xres = window.contents.ew_res
    yres = window.contents.ns_res

    outrast = []
    for i in range(nrows):
        outrast[i:] = [Rast_allocate_d_buf()]

    # create new raster
    outfd = Rast_open_new(output, DCELL_TYPE)
    if outfd < 0:
        grass.fatal("Impossible to create a raster <%s>" % output)

    # insert null values in cells
    grass.message(_("Step 1/4: Inserting null values in cells..."))
    for i in range(nrows):
        Rast_set_d_null_value(outrast[i], ncols)
        G_percent(i, nrows, 2)

    #####  main work #####
    grass.message(_("Step 2/4: TIN preprocessing..."))
    z = c_double()
    G_percent(0, nrows, 2)
    Vect_tin_get_z(map_info, xref, yref, byref(z), None, None)

    grass.message(_("Step 3/4: Converting TIN to raster..."))
    for i in range(nrows):
        for j in range(ncols):
            x = xref + j * xres
            y = yref + i * yres
            Vect_tin_get_z(map_info, x, y, byref(z), None, None)
            outrast[i][j] = z
        G_percent(i, nrows, 2)

    grass.message(_("Step 4/4: Writing raster map..."))

    for i in range(nrows - 1, -1, -1):
        Rast_put_d_row(outfd, outrast[i])
        G_percent(nrows - i, nrows, 2)

    # clear buffer
    for i in range(nrows):
        G_free(outrast[i])

    # close raster
    Rast_close(outfd)

    # close vector
    Vect_close(map_info)

    # cut output raster to TIN vertical range
    vtop = grass.read_command("v.info", flags="g", map=input).rsplit()[4].split("=")[1]
    vbottom = grass.read_command("v.info", flags="g", map=input).rsplit()[5].split("=")[1]

    tmp = "v_tin_to_rast_%d" % os.getpid()
    grass.mapcalc(
        "$tmp = if($vbottom < $output && $output < $vtop, $output, null())",
        tmp=tmp,
        output=output,
        vbottom=vbottom,
        vtop=vtop,
        quiet=True,
        stderr=nuldev,
    )

    grass.parse_command("g.rename", rast=(tmp, output), quiet=True, stderr=nuldev)

    # write cmd history:
    grass.run_command(
        "r.support", map=output, title="%s" % output, history="", description="generated by v.tin.to.rast"
    )
    grass.raster_history(output)

    grass.message(_("Done."))
Example #24
0
def main():
    global tile, tmpdir, in_temp

    in_temp = False

    input = options['input']
    output = options['output']
    one = flags['1']

    #are we in LatLong location?
    s = grass.read_command("g.proj", flags='j')
    kv = grass.parse_key_val(s)
    if kv['+proj'] != 'longlat':
	grass.fatal(_("This module only operates in LatLong locations"))

    # use these from now on:
    infile = input
    while infile[-4:].lower() in ['.hgt', '.zip']:
	infile = infile[:-4]
    (fdir, tile) = os.path.split(infile)

    if not output:
	tileout = tile
    else:
	tileout = output

    zipfile = infile + ".hgt.zip"
    hgtfile = os.path.join(fdir, tile[:7] + ".hgt")
    if os.path.isfile(zipfile):
        #### check if we have unzip
	if not grass.find_program('unzip'):
	    grass.fatal(_('The "unzip" program is required, please install it first'))

	# really a ZIP file?
	# make it quiet in a safe way (just in case -qq isn't portable)
	tenv = os.environ.copy()
	tenv['UNZIP'] = '-qq'
	if grass.call(['unzip', '-t', zipfile], env = tenv) != 0:
	    grass.fatal(_("'%s' does not appear to be a valid zip file.") % zipfile)

	is_zip = True
    elif os.path.isfile(hgtfile):
	# try and see if it's already unzipped
	is_zip = False
    else:
	grass.fatal(_("File '%s' or '%s' not found") % (zipfile, hgtfile))

    #make a temporary directory
    tmpdir = grass.tempfile()
    grass.try_remove(tmpdir)
    os.mkdir(tmpdir)

    if is_zip:
	shutil.copyfile(zipfile, os.path.join(tmpdir, tile + ".hgt.zip"))
    else:
	shutil.copyfile(hgtfile, os.path.join(tmpdir, tile + ".hgt"))

    #change to temporary directory
    os.chdir(tmpdir)
    in_temp = True

    zipfile = tile + ".hgt.zip"
    hgtfile = tile[:7] + ".hgt"
    bilfile = tile + ".bil"

    if is_zip:
        #unzip & rename data file:
	grass.message(_("Extracting '%s'...") % infile)
	if grass.call(['unzip', zipfile], env = tenv) != 0:
	    grass.fatal(_("Unable to unzip file."))

    grass.message(_("Converting input file to BIL..."))
    os.rename(hgtfile, bilfile)

    north = tile[0]
    ll_latitude  = int(tile[1:3])
    east = tile[3]
    ll_longitude = int(tile[4:7])

    # are we on the southern hemisphere? If yes, make LATITUDE negative.
    if north == "S":
	ll_latitude *= -1

    # are we west of Greenwich? If yes, make LONGITUDE negative.
    if east == "W":
	ll_longitude *= -1

    # Calculate Upper Left from Lower Left
    ulxmap = "%.1f" % ll_longitude
    # SRTM90 tile size is 1 deg:
    ulymap = "%.1f" % (ll_latitude + 1)

    if not one:
	tmpl = tmpl3sec
    else:
	grass.message(_("Attempting to import 1-arcsec data."))
	tmpl = tmpl1sec

    header = tmpl % (ulxmap, ulymap)
    hdrfile = tile + '.hdr'
    outf = file(hdrfile, 'w')
    outf.write(header)
    outf.close()

    #create prj file: To be precise, we would need EGS96! But who really cares...
    prjfile = tile + '.prj'
    outf = file(prjfile, 'w')
    outf.write(proj)
    outf.close()

    try:
        grass.run_command('r.in.gdal', input=bilfile, out=tileout)
    except:
        grass.fatal(_("Unable to import data"))

    # nice color table
    grass.run_command('r.colors', map = tileout, color = 'srtm')

    # write cmd history:
    grass.raster_history(tileout)

    grass.message(_("Done: generated map ") + tileout)
    grass.message(_("(Note: Holes in the data can be closed with 'r.fillnulls' using splines)"))
Example #25
0
def main():
    global tmp

    landsat = flags['l']
    quickbird = flags['q']
    spot = flags['s']

    ms1 = options['ms1']
    ms2 = options['ms2']
    ms3 = options['ms3']
    pan = options['pan']
    out = options['output_prefix']

    tmp = str(os.getpid())

    if not landsat and not quickbird and not spot:
	grass.fatal(_("Please select a flag to specify the satellite sensor"))

    #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.verbose("Using resolution from PAN: %f" % panres)
    grass.run_command('g.region', flags = 'a', res = panres)

    grass.verbose("Performing Brovey transformation...")

    # The formula was originally developed for LANDSAT-TM5 and SPOT, 
    # but it also works well with LANDSAT-TM7
    # LANDSAT formula:
    #  r.mapcalc "brov.red=1. *  tm.5 / (tm.2 + tm.4 + tm.5) * etmpan"
    #  r.mapcalc "brov.green=1. * tm.4 /(tm.2 + tm.4 + tm.5) * etmpan"
    #  r.mapcalc "brov.blue=1. * tm.2 / (tm.2 + tm.4 + tm.5) * etmpan"
    #
    # SPOT formula:
    # r.mapcalc "brov.red= 1.  * spot.ms.3 / (spot.ms.1 + spot.ms.2 + spot.ms.3) * spot.p"
    # r.mapcalc "brov.green=1. * spot.ms.2 / (spot.ms.1 + spot.ms.2 + spot.ms.3) * spot.p"
    # r.mapcalc "brov.blue= 1. * spot.ms.1 / (spot.ms.1 + spot.ms.2 + spot.ms.3) * spot.p"
    # note: for RGB composite then revert brov.red and brov.green!

    grass.message(_("Calculating %s.{red,green,blue}: ...") % out)
    e = '''eval(k = float("$pan") / ("$ms1" + "$ms2" + "$ms3"))
	   "$out.red"   = "$ms3" * k
	   "$out.green" = "$ms2" * k
	   "$out.blue"  = "$ms1" * k'''
    grass.mapcalc(e, out = out, pan = pan, ms1 = ms1, ms2 = ms2, ms3 = ms3)

    # Maybe?
    #r.colors   $GIS_OPT_OUTPUTPREFIX.red col=grey
    #r.colors   $GIS_OPT_OUTPUTPREFIX.green col=grey
    #r.colors   $GIS_OPT_OUTPUTPREFIX.blue col=grey
    #to blue-ish, therefore we modify
    #r.colors $GIS_OPT_OUTPUTPREFIX.blue col=rules << EOF
    #5 0 0 0
    #20 200 200 200
    #40 230 230 230
    #67 255 255 255
    #EOF

    if spot:
        #apect table is nice for SPOT:
	grass.message(_("Assigning color tables for SPOT..."))
	for ch in ['red', 'green', 'blue']:
	    grass.run_command('r.colors', map = "%s.%s" % (out, ch), col = 'aspect')
	grass.message(_("Fixing output names..."))
	for s, d in [('green','tmp'),('red','green'),('tmp','red')]:
	    src = "%s.%s" % (out, s)
	    dst = "%s.%s" % (out, d)
	    grass.run_command('g.rename', rast = (src, dst), quiet = True)
    else:
	#aspect table is nice for LANDSAT and QuickBird:
	grass.message(_("Assigning color tables for LANDSAT or QuickBird..."))
	for ch in ['red', 'green', 'blue']:
	    grass.run_command('r.colors', map = "%s.%s" % (out, ch), col = 'aspect')

    grass.message(_("Following pan-sharpened output maps have been generated:"))
    for ch in ['red', 'green', 'blue']:
	grass.message(_("%s.%s") % (out, ch))

    grass.verbose("To visualize output, run:")
    grass.verbose("g.region -p rast=%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 with 'r.composite' to a single map.")

    # write cmd history:
    for ch in ['red', 'green', 'blue']:
	grass.raster_history("%s.%s" % (out, ch))
Example #26
0
def main():
    global tmp

    landsat = flags['l']
    quickbird = flags['q']
    spot = flags['s']

    ms1 = options['ms1']
    ms2 = options['ms2']
    ms3 = options['ms3']
    pan = options['pan']
    out = options['output_prefix']

    tmp = str(os.getpid())

    if not landsat and not quickbird and not spot:
        grass.fatal(_("Please select a flag to specify the satellite sensor"))

    # 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.verbose("Using resolution from PAN: %f" % panres)
    grass.run_command('g.region', flags='a', res=panres)

    grass.verbose("Performing Brovey transformation...")

    # The formula was originally developed for LANDSAT-TM5 and SPOT,
    # but it also works well with LANDSAT-TM7
    # LANDSAT formula:
    #  r.mapcalc "brov.red=1. *  tm.5 / (tm.2 + tm.4 + tm.5) * etmpan"
    #  r.mapcalc "brov.green=1. * tm.4 /(tm.2 + tm.4 + tm.5) * etmpan"
    #  r.mapcalc "brov.blue=1. * tm.2 / (tm.2 + tm.4 + tm.5) * etmpan"
    #
    # SPOT formula:
    # r.mapcalc "brov.red= 1.  * spot.ms.3 / (spot.ms.1 + spot.ms.2 + spot.ms.3) * spot.p"
    # r.mapcalc "brov.green=1. * spot.ms.2 / (spot.ms.1 + spot.ms.2 + spot.ms.3) * spot.p"
    # r.mapcalc "brov.blue= 1. * spot.ms.1 / (spot.ms.1 + spot.ms.2 + spot.ms.3) * spot.p"
    # note: for RGB composite then revert brov.red and brov.green!

    grass.message(_("Calculating %s.{red,green,blue}: ...") % out)
    e = '''eval(k = float("$pan") / ("$ms1" + "$ms2" + "$ms3"))
        "$out.red"   = "$ms3" * k
        "$out.green" = "$ms2" * k
        "$out.blue"  = "$ms1" * k'''
    grass.mapcalc(e, out=out, pan=pan, ms1=ms1, ms2=ms2, ms3=ms3)

    # Maybe?
    # r.colors   $GIS_OPT_OUTPUTPREFIX.red col=grey
    # r.colors   $GIS_OPT_OUTPUTPREFIX.green col=grey
    # r.colors   $GIS_OPT_OUTPUTPREFIX.blue col=grey
    # to blue-ish, therefore we modify
    # r.colors $GIS_OPT_OUTPUTPREFIX.blue col=rules << EOF
    # 5 0 0 0
    # 20 200 200 200
    # 40 230 230 230
    # 67 255 255 255
    # EOF

    if spot:
        # aspect table is nice for SPOT:
        grass.message(_("Assigning color tables for SPOT..."))
        for ch in ['red', 'green', 'blue']:
            grass.run_command('r.colors',
                              map="%s.%s" % (out, ch),
                              col='aspect')
        grass.message(_("Fixing output names..."))
        for s, d in [('green', 'tmp'), ('red', 'green'), ('tmp', 'red')]:
            src = "%s.%s" % (out, s)
            dst = "%s.%s" % (out, d)
            grass.run_command('g.rename', raster=(src, dst), quiet=True)
    else:
        # aspect table is nice for LANDSAT and QuickBird:
        grass.message(_("Assigning color tables for LANDSAT or QuickBird..."))
        for ch in ['red', 'green', 'blue']:
            grass.run_command('r.colors',
                              map="%s.%s" % (out, ch),
                              col='aspect')

    grass.message(
        _("Following pan-sharpened output maps have been generated:"))
    for ch in ['red', 'green', 'blue']:
        grass.message(_("%s.%s") % (out, ch))

    grass.verbose("To visualize output, run:")
    grass.verbose("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 with 'r.composite' to a single map.")

    # write cmd history:
    for ch in ['red', 'green', 'blue']:
        grass.raster_history("%s.%s" % (out, ch))
Example #27
0
def main():
    red = options['red']
    green = options['green']
    blue = options['blue']
    brightness = options['strength']
    full = flags['f']
    preserve = flags['p']
    reset = flags['r']
    
    global do_mp

    if flags['s']:
        do_mp = False

    # 90 or 98? MAX value controls brightness
    # think of percent (0-100), must be positive or 0
    # must be more than "2" ?

    if full:
	for i in [red, green, blue]:
	    grass.run_command('r.colors', map = i, color = 'grey', quiet = True)
	sys.exit(0)

    if reset:
	for i in [red, green, blue]:
	    grass.run_command('r.colors', map = i, color = 'grey255', quiet = True)
	sys.exit(0)


    if not preserve:
        if do_mp:
            grass.message(_("Processing..."))
	    # set up jobs and launch them
	    proc = {}
	    conn = {}
	    for i in [red, green, blue]:
	        conn[i] = mp.Pipe()
	        proc[i] = mp.Process(target = get_percentile_mp,
				     args = (i, ['2', brightness],
				     conn[i],))
		proc[i].start()
            grass.percent(1, 2, 1)
            
	    # collect results and wait for jobs to finish
	    for i in [red, green, blue]:
		output_pipe, input_pipe = conn[i]
		(v0, v1) = input_pipe.recv()
		grass.debug('parent (%s) (%.1f, %.1f)' % (i, v0, v1))
		input_pipe.close()
		proc[i].join()
		set_colors(i, v0, v1)
            grass.percent(1, 1, 1)
	else:
	    for i in [red, green, blue]:
	        grass.message(_("Processing..."))
	        (v0, v1) = get_percentile(i, ['2', brightness])
	        grass.debug("<%s>:  min=%f   max=%f" % (i, v0, v1))
	        set_colors(i, v0, v1)

    else:
	all_max = 0
	all_min = 999999

	if do_mp:
	    grass.message(_("Processing..."))
	    # set up jobs and launch jobs
	    proc = {}
	    conn = {}
	    for i in [red, green, blue]:
		conn[i] = mp.Pipe()
		proc[i] = mp.Process(target = get_percentile_mp,
				     args = (i, ['2', brightness],
				     conn[i],))
		proc[i].start()
            grass.percent(1, 2, 1)
            
	    # collect results and wait for jobs to finish
	    for i in [red, green, blue]:
		output_pipe, input_pipe = conn[i]
		(v0, v1) = input_pipe.recv()
		grass.debug('parent (%s) (%.1f, %.1f)' % (i, v0, v1))
		input_pipe.close()
		proc[i].join()
		all_min = min(all_min, v0)
		all_max = max(all_max, v1)
            grass.percent(1, 1, 1)
	else:
	    for i in [red, green, blue]:
		grass.message(_("Processing..."))
		(v0, v1) = get_percentile(i, ['2', brightness])
		grass.debug("<%s>:  min=%f   max=%f" % (i, v0, v1))
		all_min = min(all_min, v0)
		all_max = max(all_max, v1)

	grass.debug("all_min=%f   all_max=%f" % (all_min, all_max))
	for i in [red, green, blue]:
	    set_colors(i, all_min, all_max)


    # write cmd history:
    mapset = grass.gisenv()['MAPSET']
    for i in [red, green, blue]:
        if grass.find_file(i)['mapset'] == mapset:
            grass.raster_history(i)
Example #28
0
def main():
    global vecttmp, tmp1, usermask, mapset

    input = options['input']
    output = options['output']
    tension = options['tension']
    smooth = options['smooth']

    mapset = grass.gisenv()['MAPSET']
    unique = str(os.getpid())

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

    # check if a MASK is already present:
    usermask = "usermask_mask." + unique
    if grass.find_file('MASK', mapset = mapset)['file']:
	grass.message(_("A user raster mask (MASK) is present. Saving it..."))
	grass.run_command('g.rename', quiet = True, rast = ('MASK',usermask))

    #make a mask of NULL cells
    tmp1 = "r_fillnulls_" + unique

    # idea: filter all NULLS and grow that area(s) by 3 pixel, then
    # interpolate from these surrounding 3 pixel edge

    grass.message(_("Locating and isolating NULL areas..."))
    #creating 0/1 map:
    grass.mapcalc("$tmp1 = if(isnull($input),1,null())",
		  tmp1 = tmp1, input = input)

    #generate a ring:
    # the buffer is set to three times the map resolution so you get nominally
    # three points around the edge. This way you interpolate into the hole with 
    # a trained slope & curvature at the edges, otherwise you just get a flat plane.
    # With just a single row of cells around the hole you often get gaps
    # around the edges when distance > mean (.5 of the time? diagonals? worse 
    # when ewres!=nsres).
    # r.buffer broken in trunk for latlon, disabled

    #reg = grass.region()
    #res = (float(reg['nsres']) + float(reg['ewres'])) * 3 / 2

    #if grass.run_command('r.buffer', input = tmp1, distances = res, out = tmp1 + '.buf') != 0:

    # much easier way: use r.grow with radius=3.01
    if grass.run_command('r.grow', input = tmp1, radius = 3.01, old = 1, new = 2, out = tmp1 + '.buf') != 0:
	grass.fatal(_("abandoned. Removing temporary map, restoring user mask if needed:"))

    grass.mapcalc("MASK=if($tmp1.buf==2,1,null())", tmp1 = tmp1)

    # now we only see the outlines of the NULL areas if looking at INPUT.
    # Use this outline (raster border) for interpolating the fill data:
    vecttmp = "vecttmp_fillnulls_" + unique
    grass.message(_("Creating interpolation points..."))
    if grass.run_command('r.to.vect', input = input, output = vecttmp, feature = 'point'):
	grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:"))

    # count number of points to control segmax parameter for interpolation:
    pointsnumber = grass.vector_info_topo(map = vecttmp)['points']

    grass.message(_("Interpolating %d points") % pointsnumber)

    if pointsnumber < 2:
	grass.fatal(_("Not sufficient points to interpolate. Maybe no hole(s) to fill in the current map region?"))

    grass.message(_("Note: The following warnings may be ignored."))

    # remove internal MASK first -- WHY???? MN 10/2005
    grass.run_command('g.remove', quiet = True, rast = 'MASK')

    if grass.find_file(usermask, mapset = mapset)['file']:
	grass.message(_("Using user mask while interpolating"))
	maskmap = usermask
    else:
	maskmap = None

    segmax = 600
    if pointsnumber > segmax:
	grass.message(_("Using segmentation for interpolation..."))
	segmax = None
    else:
	grass.message(_("Using no segmentation for interpolation as not needed..."))

    grass.run_command('v.surf.rst', input = vecttmp, elev = tmp1 + '_filled',
		      zcol = 'value', tension = tension, smooth = smooth,
		      maskmap = maskmap, segmax = segmax)

    grass.message(_("Note: Above warnings may be ignored."))

    # restoring user's mask, if present:
    if grass.find_file(usermask, mapset = mapset)['file']:
	grass.message(_("Restoring user mask (MASK)..."))
	grass.run_command('g.rename', quiet = True, rast = (usermask, 'MASK'))

    # patch orig and fill map
    grass.message(_("Patching fill data into NULL areas..."))
    # we can use --o here as g.parser already checks on startup
    grass.run_command('r.patch', input = (input,tmp1 + '_filled'), output = output, overwrite = True)

    grass.message(_("Filled raster map is: %s") % output)

    # write cmd history:
    grass.raster_history(output)

    grass.message(_("Done."))
Example #29
0
def main():
    atexit.register(cleanup)
    options, flags = gscript.parser()

    elevation_input = options["input"]
    local_relief_output = options["output"]
    neighborhood_size = int(options["neighborhood_size"])
    save_intermediates = flags["i"]
    bspline = flags["v"]  # when bspline == False, r.fillnulls is used

    shaded_local_relief_output = options["shaded_output"]

    # constants
    fill_method = "bicubic"
    # color table changed from difference to grey to histogram equalized-grey
    # It does make more sense to use that since many archaeologists use the same
    # color scheme for magnetometry and gpr data.
    color_table = options["color_table"]
    if color_table:
        user_color_table = True
    else:
        user_color_table = False
    rcolors_flags = "e"
    if flags["f"]:
        rcolors_flags = ""
    if flags["g"]:
        rcolors_flags += "g"
    if flags["n"]:
        rcolors_flags += "n"

    if save_intermediates:

        def local_create(name):
            """create_persistent_map_name with hard-coded first argument"""
            basename = local_relief_output.split("@")[0]
            return create_persistent_map_name(basename=basename, name=name)

        create_map_name = local_create
    else:
        create_map_name = create_tmp_map_name

    smooth_elevation = create_map_name("smooth_elevation")
    subtracted_smooth_elevation = create_map_name(
        "subtracted_smooth_elevation")
    vector_contours = create_map_name("vector_contours")
    raster_contours_with_values = create_map_name(
        "raster_contours_with_values")
    purged_elevation = create_map_name("purged_elevation")

    if bspline:
        contour_points = create_map_name("contour_points")
    else:
        raster_contours = create_map_name("raster_contours")

    if shaded_local_relief_output:
        relief_shade = create_map_name("relief_shade")

    # if saving intermediates, keep only 1 contour layer
    if save_intermediates:
        if not bspline:
            RREMOVE.append(raster_contours)
            VREMOVE.append(vector_contours)
    else:
        RREMOVE.append(smooth_elevation)
        RREMOVE.append(subtracted_smooth_elevation)
        VREMOVE.append(vector_contours)
        RREMOVE.append(purged_elevation)
        if bspline:
            VREMOVE.append(contour_points)
        else:
            RREMOVE.append(raster_contours)
            RREMOVE.append(raster_contours_with_values)

    # check even for the temporary maps
    # (although, in ideal world, we should always fail if some of them exists)
    if not gcore.overwrite():
        check_map_name(smooth_elevation, gscript.gisenv()["MAPSET"], "cell")
        check_map_name(subtracted_smooth_elevation,
                       gscript.gisenv()["MAPSET"], "cell")
        check_map_name(vector_contours, gscript.gisenv()["MAPSET"], "vect")
        check_map_name(raster_contours_with_values,
                       gscript.gisenv()["MAPSET"], "cell")
        check_map_name(purged_elevation, gscript.gisenv()["MAPSET"], "cell")
        if bspline:
            check_map_name(contour_points, gscript.gisenv()["MAPSET"], "vect")
        else:
            check_map_name(raster_contours, gscript.gisenv()["MAPSET"], "cell")

    # algorithm according to Hesse 2010 (LiDAR-derived Local Relief Models)
    # step 1 (point cloud to digital elevation model) omitted

    # step 2
    gscript.info(_("Smoothing using r.neighbors..."))
    gscript.run_command(
        "r.neighbors",
        input=elevation_input,
        output=smooth_elevation,
        size=neighborhood_size,
        overwrite=gcore.overwrite(),
    )

    # step 3
    gscript.info(_("Subtracting smoothed from original elevation..."))
    gscript.mapcalc("{c} = {a} - {b}".format(
        c=subtracted_smooth_elevation,
        a=elevation_input,
        b=smooth_elevation,
        overwrite=gcore.overwrite(),
    ))

    # step 4
    gscript.info(_("Finding zero contours in elevation difference map..."))
    gscript.run_command(
        "r.contour",
        input=subtracted_smooth_elevation,
        output=vector_contours,
        levels=[0],
        overwrite=gcore.overwrite(),
    )

    # Diverge here if using bspline interpolation
    # step 5
    gscript.info(
        _("Extracting z value from the elevation"
          " for difference zero contours..."))
    if bspline:
        # Extract points from vector contours
        gscript.run_command(
            "v.to.points",
            _input=vector_contours,
            llayer="1",
            _type="line",
            output=contour_points,
            dmax="10",
            overwrite=gcore.overwrite(),
        )

        # Extract original dem elevations at point locations
        gscript.run_command(
            "v.what.rast",
            _map=contour_points,
            raster=elevation_input,
            layer="2",
            column="along",
        )

        # Get mean distance between points to optimize spline interpolation
        mean_dist = gscript.parse_command(
            "v.surf.bspline",
            flags="e",
            _input=contour_points,
            raster_output=purged_elevation,
            layer="2",
            column="along",
            method=fill_method,
        )
        spline_step = round(float(mean_dist.keys()[0].split(" ")[-1])) * 2

        gscript.info(
            _("Interpolating purged surface using a spline step value"
              " of {s}".format(s=spline_step)))
        gscript.run_command(
            "v.surf.bspline",
            _input=contour_points,
            raster_output=purged_elevation,
            layer="2",
            column="along",
            method=fill_method,
            overwrite=gcore.overwrite(),
        )
    else:
        gscript.run_command(
            "v.to.rast",
            input=vector_contours,
            output=raster_contours,
            type="line",
            use="val",
            value=1,
            overwrite=gcore.overwrite(),
        )
        gscript.mapcalc("{c} = {a} * {b}".format(
            c=raster_contours_with_values,
            a=raster_contours,
            b=elevation_input,
            overwrite=gcore.overwrite(),
        ))

        gscript.info(
            _("Interpolating elevation between"
              " difference zero contours..."))
        gscript.run_command(
            "r.fillnulls",
            input=raster_contours_with_values,
            output=purged_elevation,
            method=fill_method,
            overwrite=gcore.overwrite(),
        )

    # step 6
    gscript.info(_("Subtracting purged from original elevation..."))
    gscript.mapcalc("{c} = {a} - {b}".format(
        c=local_relief_output,
        a=elevation_input,
        b=purged_elevation,
        overwrite=gcore.overwrite(),
    ))

    gscript.raster_history(local_relief_output)

    # set color tables
    if save_intermediates:
        # same color table as input
        gscript.run_command("r.colors",
                            map=smooth_elevation,
                            raster=elevation_input,
                            quiet=True)
        gscript.run_command("r.colors",
                            map=purged_elevation,
                            raster=elevation_input,
                            quiet=True)

        # has only one color
        if not bspline:
            gscript.run_command(
                "r.colors",
                map=raster_contours_with_values,
                raster=elevation_input,
                quiet=True,
            )

        # same color table as output
        gscript.run_command("r.colors",
                            map=subtracted_smooth_elevation,
                            color=color_table,
                            quiet=True)

    if shaded_local_relief_output:
        if not user_color_table:
            color_table = "difference"
        gscript.run_command(
            "r.colors",
            flags=rcolors_flags,
            map=local_relief_output,
            color=color_table,
            quiet=True,
        )
        # r.relief could run in parallel to the main computation,
        # but it is probably fast in comparison to the rest.
        # In theory, r.skyview and first component from r.shaded.pca
        # can be added as well, but let's leave this to the user.
        gscript.run_command("r.relief",
                            input=elevation_input,
                            output=relief_shade)
        gscript.run_command(
            "r.shade",
            shade=relief_shade,
            color=local_relief_output,
            output=shaded_local_relief_output,
        )
        if not user_color_table:
            color_table = "grey"
            gscript.run_command(
                "r.colors",
                flags=rcolors_flags,
                map=local_relief_output,
                color=color_table,
                quiet=True,
            )
        gscript.raster_history(shaded_local_relief_output)
    else:
        if not user_color_table:
            color_table = "grey"
        gscript.run_command(
            "r.colors",
            flags=rcolors_flags,
            map=local_relief_output,
            color=color_table,
            quiet=True,
        )
Example #30
0
def main():
    red = options["red"]
    green = options["green"]
    blue = options["blue"]
    brightness = options["strength"]
    full = flags["f"]
    preserve = flags["p"]
    reset = flags["r"]

    global do_mp

    if flags["s"]:
        do_mp = False

    check = True
    for m in [red, green, blue]:
        ex = gscript.find_file(m)
        if ex["name"] == "":
            check = False
            gscript.warning("Raster map <{}> not found ".format(m))
    if not check:
        gscript.fatal("At least one of the input raster map was not found")
    # 90 or 98? MAX value controls brightness
    # think of percent (0-100), must be positive or 0
    # must be more than "2" ?

    if full:
        for i in [red, green, blue]:
            gscript.run_command("r.colors", map=i, color="grey", quiet=True)
        sys.exit(0)

    if reset:
        for i in [red, green, blue]:
            gscript.run_command("r.colors", map=i, color="grey255", quiet=True)
        sys.exit(0)

    if not preserve:
        if do_mp:
            gscript.message(_("Processing..."))
            # set up jobs and launch them
            proc = {}
            conn = {}
            for i in [red, green, blue]:
                conn[i] = mp.Pipe()
                proc[i] = mp.Process(
                    target=get_percentile_mp,
                    args=(
                        i,
                        ["2", brightness],
                        conn[i],
                    ),
                )
                proc[i].start()
            gscript.percent(1, 2, 1)

            # collect results and wait for jobs to finish
            for i in [red, green, blue]:
                output_pipe, input_pipe = conn[i]
                (v0, v1) = input_pipe.recv()
                gscript.debug("parent (%s) (%.1f, %.1f)" % (i, v0, v1))
                input_pipe.close()
                proc[i].join()
                set_colors(i, v0, v1)
            gscript.percent(1, 1, 1)
        else:
            for i in [red, green, blue]:
                gscript.message(_("Processing..."))
                (v0, v1) = get_percentile(i, ["2", brightness])
                gscript.debug("<%s>:  min=%f   max=%f" % (i, v0, v1))
                set_colors(i, v0, v1)

    else:
        all_max = 0
        all_min = 999999

        if do_mp:
            gscript.message(_("Processing..."))
            # set up jobs and launch jobs
            proc = {}
            conn = {}
            for i in [red, green, blue]:
                conn[i] = mp.Pipe()
                proc[i] = mp.Process(
                    target=get_percentile_mp,
                    args=(
                        i,
                        ["2", brightness],
                        conn[i],
                    ),
                )
                proc[i].start()
            gscript.percent(1, 2, 1)

            # collect results and wait for jobs to finish
            for i in [red, green, blue]:
                output_pipe, input_pipe = conn[i]
                (v0, v1) = input_pipe.recv()
                gscript.debug("parent (%s) (%.1f, %.1f)" % (i, v0, v1))
                input_pipe.close()
                proc[i].join()
                all_min = min(all_min, v0)
                all_max = max(all_max, v1)
            gscript.percent(1, 1, 1)
        else:
            for i in [red, green, blue]:
                gscript.message(_("Processing..."))
                (v0, v1) = get_percentile(i, ["2", brightness])
                gscript.debug("<%s>:  min=%f   max=%f" % (i, v0, v1))
                all_min = min(all_min, v0)
                all_max = max(all_max, v1)

        gscript.debug("all_min=%f   all_max=%f" % (all_min, all_max))
        for i in [red, green, blue]:
            set_colors(i, all_min, all_max)

    # write cmd history:
    mapset = gscript.gisenv()["MAPSET"]
    for i in [red, green, blue]:
        if gscript.find_file(i)["mapset"] == mapset:
            gscript.raster_history(i)
Example #31
0
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)
Example #32
0
def main(options, flags):
    # options and flags into variables
    ipl = options['input']
    raster_exists(ipl)
    opl = options['output']
    # size option backwards compatibility with window
    if not options['size'] and not options['window']:
        gs.fatal(_("Required parameter <%s> not set") % 'size')
    if options['size']:
        wz = int(options['size'])
    if options['window']:
        gs.warning(_("The window option is deprecated, use the option"
                     " size instead"))
        wz = int(options['window'])
    if options['size'] and options['size'] != '3' and options['window']:
        gs.warning(_("When the obsolete window option is used, the"
                     " new size option is ignored"))
    if wz % 2 == 0:
        gs.fatal(_("Please provide an odd number for the moving"
                   " window size, not %d") % wz)
    # user wants pf or pff
    user_pf = options['pf']
    user_pff = options['pff']
    # backwards compatibility
    if flags['t']:
        gs.warning(_("The -t flag is deprecated, use pf and pff options"
                     " instead"))
    if not user_pf and not user_pff and flags['t']:
        user_pf = opl + '_pf'
        user_pff = opl + '_pff'
    elif flags['t']:
        gs.warning(_("When pf or pff option is used, the -t flag"
                     " is ignored"))
    flag_r = flags['r']
    flag_s = flags['s']
    clip_output = flags['a']

    # set to current input map region if requested by the user
    # default is (and should be) the current region
    # we could use tmp region for this but if the flag is there
    # it makes sense to use it from now on (but we should reconsider)
    if flag_r:
        gs.message(_("Setting region to input map..."))
        gs.run_command('g.region', raster=ipl, quiet=True)

    # check if map values are limited to 1 and 0
    input_info = gs.raster_info(ipl)
    # we know what we are doing only when input is integer
    if input_info['datatype'] != 'CELL':
        gs.fatal(_("The input raster map must have type CELL"
                   " (integer)"))
    # for integer, we just need to text min and max
    if input_info['min'] != 0 or input_info['max'] != 1:
        gs.fatal(_("The input raster map must be a binary raster,"
                   " i.e. it should contain only values 0 and 1"
                   " (now the minimum is %d and maximum is %d)")
                 % (input_info['min'], input_info['max']))

    # computing pf values
    # let forested pixels be x and number of all pixels in moving window
    # be y, then pf=x/y"

    gs.info(_("Step 1: Computing Pf values..."))

    # generate grid with pixel-value=number of forest-pixels in window
    # generate grid with pixel-value=number of pixels in moving window:
    tmpA2 = tmpname('tmpA01_')
    tmpC3 = tmpname('tmpA02_')
    gs.run_command("r.neighbors", quiet=True, input=ipl,
                   output=[tmpA2, tmpC3], method=["sum", "count"], size=wz)

    # create pf map
    if user_pf:
        pf = user_pf
    else:
        pf = tmpname('tmpA03_')
    mapcalc("$pf = if( $ipl >=0, float($tmpA2) / float($tmpC3))",
            ipl=ipl, pf=pf, tmpA2=tmpA2, tmpC3=tmpC3)

    # computing pff values
    # Considering pairs of pixels in cardinal directions in
    # a 3x3 window, the total number of adjacent pixel pairs is 12.
    # Assuming that x pairs include at least one forested pixel, and
    # y of those pairs are forest-forest pairs, so pff equals y/x.

    gs.info(_("Step 2: Computing Pff values..."))

    # create copy of forest map and convert NULL to 0 (if any)
    tmpC4 = tmpname('tmpA04_')
    gs.run_command("g.copy", raster=[ipl, tmpC4], quiet=True)
    gs.run_command("r.null", map=tmpC4, null=0, quiet=True)

    # window dimensions
    max_index = int((wz - 1) / 2)
    # number of 'forest-forest' pairs
    expr1 = pairs_expression(map_name=tmpC4, max_index=max_index,
                             combine_op='&')
    # number of 'nonforest-forest' pairs
    expr2 = pairs_expression(map_name=tmpC4, max_index=max_index,
                             combine_op='|')
    # create pff map
    if user_pff:
        pff = user_pff
    else:
        pff = tmpname('tmpA07_')
    # potentially this can be split and parallelized
    mapcalc("$pff = if($ipl >= 0, float($tmpl4) / float($tmpl5))",
            ipl=ipl, tmpl4=expr1, tmpl5=expr2, pff=pff)

    # computing fragmentation index
    # (a b) name, condition
    # where a is a number used by Riitters et al. in ERRATUM (2)
    # and b is a number used in the sh script by Sambale and Sylla
    # b also defines 0 for non-forested which is consistent with input
    # (1 3) edge, if Pf > 0.6 and Pf - Pff < 0
    # (2 6) undetermined, if Pf > 0.6 and Pf = Pff
    # (3 4) perforated, if Pf > 0.6 and Pf - Pff > 0
    # (4 5) interior, if Pf = 1.0
    # (5 1) patch, if Pf < 0.4
    # (6 2) transitional, if 0.4 < Pf < 0.6

    gs.info(_("Step 3: Computing fragmentation index..."))

    if clip_output:
        indexfin2 = tmpname('tmpA16_')
    else:
        indexfin2 = opl
    mapcalc(
        "eval("
        "dpf = $pf - $pff,"
        # individual classes
        "patch = if($pf < 0.4, 1, 0),"
        "transitional = if($pf >= 0.4 && $pf < 0.6, 2, 0),"
        "edge = if($pf >= 0.6 && dpf<0,3,0),"
        "perforated = if($pf > 0.6 && $pf < 1 && dpf > 0, 4, 0),"
        "interior = if($pf == 1, 5, 0),"
        "undetermined = if($pf > 0.6 && $pf < 1 && dpf == 0, 6, 0),"
        # null is considered as non-forest and we need to do it before +
        "patch = if(isnull(patch), 0, patch),"
        "transitional = if(isnull(transitional), 0, transitional),"
        "edge = if(isnull(edge), 0, edge),"
        "perforated = if(isnull(perforated), 0, perforated),"
        "interior = if(isnull(interior), 0, interior),"
        "undetermined = if(isnull(undetermined), 0, undetermined),"
        # combine classes (they don't overlap)
        # more readable than nested ifs from the ifs above
        "all = patch + transitional + edge + perforated + interior"
        " + undetermined"
        ")\n"
        # mask result by non-forest (according to the input)
        # removes the nonsense data created in the non-forested areas
        "$out = all * $binary_forest",
        out=indexfin2, binary_forest=ipl, pf=pf, pff=pff)

    # shrink the region
    if clip_output:
        gs.use_temp_region()
        reginfo = gs.parse_command("g.region", flags="gp")
        nscor = max_index * float(reginfo['nsres'])
        ewcor = max_index * float(reginfo['ewres'])
        gs.run_command("g.region",
                       n=float(reginfo['n']) - nscor,
                       s=float(reginfo['s']) + nscor,
                       e=float(reginfo['e']) - ewcor,
                       w=float(reginfo['w']) + ewcor,
                       quiet=True)
        mapcalc("$opl = $if3", opl=opl, if3=indexfin2, quiet=True)

    # create categories
    # TODO: parametrize classes (also in r.mapcalc, r.colors and desc)?
    # TODO: translatable labels?
    labels = LABELS
    gs.write_command("r.category", quiet=True, map=opl,
                     rules='-', stdin=labels, separator='space')

    # create color table
    colors = COLORS_SAMBALE
    gs.write_command("r.colors", map=opl, rules='-',
                     stdin=colors, quiet=True)

    # write metadata for main layer
    gs.run_command("r.support", map=opl,
                   title="Forest fragmentation",
                   source1="Based on %s" % ipl,
                   description="Forest fragmentation index (6 classes)")
    gs.raster_history(opl)

    # write metadata for intermediate layers
    if user_pf:
        # pf layer
        gs.run_command("r.support", map=pf,
                       title="Proportion forested",
                       units="Proportion",
                       source1="Based on %s" % ipl,
                       description="Proportion of pixels in the moving"
                                   " window that is forested")
        gs.raster_history(pf)

    if user_pff:
        # pff layer
        unused, tmphist = tempfile.mkstemp()
        text_file = open(tmphist, "w")
        long_description = """\
Proportion of all adjacent (cardinal directions only) pixel pairs that
include at least one forest pixel for which both pixels are forested.
It thus (roughly) estimates the conditional probability that, given a
pixel of forest, its neighbor is also forest.
"""
        text_file.write(long_description)
        text_file.close()
        gs.run_command("r.support", map=pff,
                       title="Conditional probability neighboring cell"
                             " is forest",
                       units="Proportion",
                       source1="Based on %s" % ipl,
                       description="Probability neighbor of forest cell"
                                   " is forest",
                       loadhistory=tmphist)
        gs.raster_history(pff)
        os.remove(tmphist)

    # report fragmentation index and names of layers created

    if flag_s:
        gs.run_command("r.report", map=opl, units=["h", "p"],
                       flags="n", page_width=50, quiet=True)

    gs.info(_("The following layers were created"))
    gs.info(_("The fragmentation index: %s") % opl)
    if user_pf:
        gs.info(_("The proportion forested (Pf): %s") % pf)
    if user_pff:
        gs.info(_("The proportion forested pixel pairs (Pff): %s") % pff)
Example #33
0
def main():
    global usermask, mapset, tmp_rmaps, tmp_vmaps

    input = options['input']
    output = options['output']
    tension = options['tension']
    smooth = options['smooth']
    method = options['method']
    edge = int(options['edge'])
    segmax = int(options['segmax'])
    npmin = int(options['npmin'])
    quiet = True # FIXME 
    
    mapset = grass.gisenv()['MAPSET']
    unique = str(os.getpid()) # Shouldn't we use temp name?
    prefix = 'r_fillnulls_%s_' % unique
    failed_list = list() # a list of failed holes. Caused by issues with v.surf.rst. Connected with #1813

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

    # save original region
    reg_org = grass.region()
    
    # check if a MASK is already present
    # and remove it to not interfere with NULL lookup part
    # as we don't fill MASKed parts!
    if grass.find_file('MASK', mapset = mapset)['file']:
        usermask = "usermask_mask." + unique
        grass.message(_("A user raster mask (MASK) is present. Saving it..."))
        grass.run_command('g.rename', quiet = quiet, rast = ('MASK',usermask))

    #check if method is rst to use v.surf.rst
    if method == 'rst':
        # idea: filter all NULLS and grow that area(s) by 3 pixel, then
        # interpolate from these surrounding 3 pixel edge
        filling = prefix + 'filled'
        
        grass.use_temp_region()
        grass.run_command('g.region', align = input, quiet = quiet)
        region = grass.region()
        ns_res = region['nsres']
        ew_res = region['ewres']
        
        grass.message(_("Using RST interpolation..."))
        grass.message(_("Locating and isolating NULL areas..."))
        
        # creating binary (0/1) map
        if usermask:
            grass.message(_("Skipping masked raster parts"))
            grass.mapcalc("$tmp1 = if(isnull($input) && !($mask == 0 || isnull($mask)),1,null())",
                tmp1 = prefix + 'nulls', input = input, mask = usermask)
        else:
            grass.mapcalc("$tmp1 = if(isnull($input),1,null())",
                tmp1 = prefix + 'nulls', input = input)
        tmp_rmaps.append(prefix + 'nulls')
            
        # restoring user's mask, if present
        # to ignore MASKed original values
        if usermask:
            grass.message(_("Restoring user mask (MASK)..."))
            if grass.run_command('g.rename', quiet = quiet, rast = (usermask, 'MASK')) != 0:
                grass.warning(_("Failed to restore user MASK!"))
            usermask = None
    
        # grow identified holes by X pixels
        grass.message(_("Growing NULL areas"))
        tmp_rmaps.append(prefix + 'grown')
        if grass.run_command('r.grow', input = prefix + 'nulls', radius = edge + 0.01,
                             old = 1, new = 1, out = prefix + 'grown', quiet = quiet) != 0:
            grass.fatal(_("abandoned. Removing temporary map, restoring user mask if needed:"))
        
        # assign unique IDs to each hole or hole system (holes closer than edge distance)
        grass.message(_("Assigning IDs to NULL areas"))
        tmp_rmaps.append(prefix + 'clumped')
        if grass.run_command('r.clump', input = prefix + 'grown', output = prefix + 'clumped', quiet = quiet) != 0:
            grass.fatal(_("abandoned. Removing temporary map, restoring user mask if needed:"))
        
        # get a list of unique hole cat's
        grass.mapcalc("$out = if(isnull($inp), null(), $clumped)",
                        out = prefix + 'holes', inp = prefix + 'nulls', clumped = prefix + 'clumped')
        tmp_rmaps.append(prefix + 'holes')
        
        # use new IDs to identify holes
        if grass.run_command('r.to.vect', flags = 'v', input = prefix + 'holes', output = prefix + 'holes',
                            type = 'area', quiet = quiet) != 0:
            grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:"))
        tmp_vmaps.append(prefix + 'holes')
        
        # get a list of unique hole cat's
        cats_file_name = grass.tempfile(False)
        grass.run_command('v.db.select', flags = 'c', map = prefix + 'holes', columns = 'cat', file = cats_file_name, quiet = quiet)
        cat_list = list()
        cats_file = file(cats_file_name)
        for line in cats_file:
            cat_list.append(line.rstrip('\n'))
        cats_file.close()
        os.remove(cats_file_name)
        
        if len(cat_list) < 1:
            grass.fatal(_("Input map has no holes. Check region settings."))
        
        # GTC Hole is NULL area in a raster map
        grass.message(_("Processing %d map holes") % len(cat_list))
        first = True
        hole_n = 1
        for cat in cat_list:
            holename = prefix + 'hole_' + cat
            # GTC Hole is a NULL area in a raster map
            grass.message(_("Filling hole %s of %s") % (hole_n, len(cat_list)))
            hole_n = hole_n + 1
            # cut out only CAT hole for processing
            if grass.run_command('v.extract', input = prefix + 'holes', output = holename + '_pol',
                                cats = cat, quiet = quiet) != 0:
                grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:"))
            tmp_vmaps.append(holename + '_pol')
            
            # zoom to specific hole with a buffer of two cells around the hole to remove rest of data
            if grass.run_command('g.region', vect = holename + '_pol', align = input, 
                                w = 'w-%d' % (edge * 2 * ew_res), e = 'e+%d' % (edge * 2 * ew_res), 
                                n = 'n+%d' % (edge * 2 * ns_res), s = 's-%d' % (edge * 2 * ns_res),
                                quiet = quiet) != 0:
                grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:"))
            
            # remove temporary map to not overfill disk
            if grass.run_command('g.remove', flags = 'fb', type = 'vect', pattern = holename + '_pol', quiet = quiet) != 0:
                grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:"))
            tmp_vmaps.remove(holename + '_pol')
            
            # copy only data around hole
            grass.mapcalc("$out = if($inp == $catn, $inp, null())",
                            out = holename, inp = prefix + 'holes', catn = cat)
            tmp_rmaps.append(holename)
            
            # If here loop is split into two, next part of loop can be run in parallel 
            # (except final result patching)
            # Downside - on large maps such approach causes large disk usage
            
            # grow hole border to get it's edge area
            tmp_rmaps.append(holename + '_grown')
            if grass.run_command('r.grow', input = holename, radius = edge + 0.01,
                             old = -1, out = holename + '_grown', quiet = quiet) != 0:
                grass.fatal(_("abandoned. Removing temporary map, restoring user mask if needed:"))
            
            # no idea why r.grow old=-1 doesn't replace existing values with NULL
            grass.mapcalc("$out = if($inp == -1, null(), $dem)", 
                            out = holename + '_edges', inp = holename + '_grown', dem = input)
            tmp_rmaps.append(holename + '_edges')
            
            # convert to points for interpolation
            tmp_vmaps.append(holename)
            if grass.run_command('r.to.vect', input = holename + '_edges', output = holename,
                                type = 'point', flags = 'z', quiet = quiet) != 0:
                grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:"))
            
            # count number of points to control segmax parameter for interpolation:
            pointsnumber = grass.vector_info_topo(map = holename)['points']
            grass.verbose(_("Interpolating %d points") % pointsnumber)

            if pointsnumber < 2:
                grass.verbose(_("No points to interpolate"))
                failed_list.append(holename)
                continue
            
            # Avoid v.surf.rst warnings
            if pointsnumber < segmax:
                npmin = pointsnumber + 1
                segmax = pointsnumber
            
            # launch v.surf.rst
            tmp_rmaps.append(holename + '_dem')
            if grass.run_command('v.surf.rst', quiet = quiet, input = holename, elev = holename + '_dem',
                                 tension = tension, smooth = smooth, 
                                 segmax = segmax, npmin = npmin) != 0:
                # GTC Hole is NULL area in a raster map
                grass.fatal(_("Failed to fill hole %s") % cat)
            
            # v.surf.rst sometimes fails with exit code 0
            # related bug #1813
            if not grass.find_file(holename + '_dem')['file']:
                try:
                    tmp_rmaps.remove(holename)
                    tmp_rmaps.remove(holename + '_grown')
                    tmp_rmaps.remove(holename + '_edges')
                    tmp_rmaps.remove(holename + '_dem')
                    tmp_vmaps.remove(holename)
                except:
                    pass
                grass.warning(_("Filling has failed silently. Leaving temporary maps with prefix <%s> for debugging.") % holename)
                failed_list.append(holename)
                continue
            
            # append hole result to interpolated version later used to patch into original DEM
            if first:
                tmp_rmaps.append(filling)
                grass.run_command('g.region', align = input, rast = holename + '_dem', quiet = quiet)
                grass.mapcalc("$out = if(isnull($inp), null(), $dem)", 
                                out = filling, inp = holename, dem = holename + '_dem')
                first = False
            else:
                tmp_rmaps.append(filling + '_tmp')
                grass.run_command('g.region', align = input, rast = (filling, holename + '_dem'), quiet = quiet)
                grass.mapcalc("$out = if(isnull($inp), if(isnull($fill), null(), $fill), $dem)", 
                                out = filling + '_tmp', inp = holename, dem = holename + '_dem', fill = filling)
                if grass.run_command('g.rename', rast = (filling + '_tmp', filling), 
                                    overwrite = True, quiet = quiet) != 0:
                    grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:"))
                tmp_rmaps.remove(filling + '_tmp') # this map has been removed. No need for later cleanup.
            
            # remove temporary maps to not overfill disk
            try:
                tmp_rmaps.remove(holename)
                tmp_rmaps.remove(holename + '_grown')
                tmp_rmaps.remove(holename + '_edges')
                tmp_rmaps.remove(holename + '_dem')
            except:
                pass
            if grass.run_command('g.remove', quiet = quiet, flags = 'fb', type = 'rast', pattern = 
                (holename, holename + '_grown', holename + '_edges', holename + '_dem')) != 0:
                grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:"))
            try:
                tmp_vmaps.remove(holename)
            except:
                pass
            if grass.run_command('g.remove', quiet = quiet, flags = 'fb', type = 'vect', pattern = holename) != 0:
                grass.fatal(_("abandoned. Removing temporary maps, restoring user mask if needed:"))
    
    #check if method is different from rst to use r.resamp.bspline
    if method != 'rst':
        grass.message(_("Using %s bspline interpolation") % method)

        # clone current region
        grass.use_temp_region()
        grass.run_command('g.region', align = input)

        reg = grass.region()
        # launch r.resamp.bspline
        tmp_rmaps.append(prefix + 'filled')
        if usermask:
            grass.run_command('r.resamp.bspline', input = input, mask = usermask,
                output = prefix + 'filled', method = method, 
                ew_step = 3 * reg['ewres'], ns_step = 3 * reg['nsres'], 
                _lambda = 0.01, flags = 'n')
        else:
            grass.run_command('r.resamp.bspline', input = input,
                output = prefix + 'filled', method = method, 
                ew_step = 3 * reg['ewres'], ns_step = 3 * reg['nsres'], 
                _lambda = 0.01, flags = 'n')

    # restoring user's mask, if present:
    if usermask:
        grass.message(_("Restoring user mask (MASK)..."))
        if grass.run_command('g.rename', quiet = quiet, rast = (usermask, 'MASK')) != 0:
            grass.warning(_("Failed to restore user MASK!"))
        usermask = None

    # set region to original extents, align to input
    grass.run_command('g.region', n = reg_org['n'], s = reg_org['s'], 
                    e = reg_org['e'], w = reg_org['w'], align = input)

    # patch orig and fill map
    grass.message(_("Patching fill data into NULL areas..."))
    # we can use --o here as g.parser already checks on startup
    grass.run_command('r.patch', input = (input,prefix + 'filled'), output = output, overwrite = True)

    # restore the real region
    grass.del_temp_region()

    grass.message(_("Filled raster map is: %s") % output)

    # write cmd history:
    grass.raster_history(output)
    
    if len(failed_list) > 0:
        grass.warning(_("Following holes where not filled. Temporary maps with are left in place to allow examination of unfilled holes"))
        outlist = failed_list[0]
        for hole in failed_list[1:]:
            outlist = ', ' + outlist
        grass.message(outlist)

    grass.message(_("Done."))
Example #34
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:
        ""
Example #35
0
def main():
    global vrtfile, tmpfile

    infile  = options['input']
    rast = options['output']
    also = flags['a']

    #### check for gdalinfo (just to check if installation is complete)
    if not grass.find_program('gdalinfo', '--help'):
	grass.fatal(_("'gdalinfo' not found, install GDAL tools first (http://www.gdal.org)"))

    pid = str(os.getpid())
    tmpfile = grass.tempfile()

    ################### let's go

    spotdir = os.path.dirname(infile)
    spotname = grass.basename(infile, 'hdf')

    if rast:
	name = rast
    else:
	name = spotname

    if not grass.overwrite() and grass.find_file(name)['file']:
	grass.fatal(_("<%s> already exists. Aborting.") % name)

    # still a ZIP file?  (is this portable?? see the r.in.srtm script for ideas)
    if infile.lower().endswith('.zip'):
	grass.fatal(_("Please extract %s before import.") % infile)

    try:
	p = grass.Popen(['file', '-ib', infile], stdout = grass.PIPE)
	s = p.communicate()[0]
	if s == "application/x-zip":
	    grass.fatal(_("Please extract %s before import.") % infile)
    except:
	pass

    ### create VRT header for NDVI

    projfile = os.path.join(spotdir, "0001_LOG.TXT")
    vrtfile = tmpfile + '.vrt'

    # first process the NDVI:
    grass.try_remove(vrtfile)
    create_VRT_file(projfile, vrtfile, infile)

    ## let's import the NDVI map...
    grass.message(_("Importing SPOT VGT NDVI map..."))
    try:
        grass.run_command('r.in.gdal', input=vrtfile, output=name)
    except CalledModuleError:
        grass.fatal(_("An error occurred. Stop."))

    grass.message(_("Imported SPOT VEGETATION NDVI map <%s>.") % name)

    #################
    ## http://www.vgt.vito.be/faq/FAQS/faq19.html
    # What is the relation between the digital number and the real NDVI ?
    # Real NDVI =coefficient a * Digital Number + coefficient b
    #           = a * DN +b
    #
    # Coefficient a = 0.004
    # Coefficient b = -0.1

    # clone current region
    # switch to a temporary region
    grass.use_temp_region()

    grass.run_command('g.region', raster = name, quiet = True)

    grass.message(_("Remapping digital numbers to NDVI..."))
    tmpname = "%s_%s" % (name, pid)
    grass.mapcalc("$tmpname = 0.004 * $name - 0.1", tmpname = tmpname, name = name)
    grass.run_command('g.remove', type = 'raster', name = name, quiet = True, flags = 'f')
    grass.run_command('g.rename', raster = (tmpname, name), quiet = True)

    # write cmd history:
    grass.raster_history(name)

    #apply color table:
    grass.run_command('r.colors', map = name, color = 'ndvi', quiet = True)

    ##########################
    # second, optionally process the SM quality map:
    
    #SM Status Map
    # http://nieuw.vgt.vito.be/faq/FAQS/faq22.html
    #Data about
    # Bit NR 7: Radiometric quality for B0 coded as 0 if bad and 1 if good
    # Bit NR 6: Radiometric quality for B2 coded as 0 if bad and 1 if good
    # Bit NR 5: Radiometric quality for B3 coded as 0 if bad and 1 if good
    # Bit NR 4: Radiometric quality for MIR coded as 0 if bad and 1 if good
    # Bit NR 3: land code 1 or water code 0
    # Bit NR 2: ice/snow code 1 , code 0 if there is no ice/snow
    # Bit NR 1:	0	0	1		1
    # Bit NR 0:	0	1	0		1
    # 		clear	shadow	uncertain	cloud
    #
    #Note:
    # pos 7     6    5    4    3    2   1   0 (bit position)
    #   128    64   32   16    8    4   2   1 (values for 8 bit)
    #
    #
    # Bit 4-7 should be 1: their sum is 240
    # Bit 3   land code, should be 1, sum up to 248 along with higher bits
    # Bit 2   ice/snow code
    # Bit 0-1 should be 0
    #
    # A good map threshold: >= 248

    if also:
	grass.message(_("Importing SPOT VGT NDVI quality map..."))
	grass.try_remove(vrtfile)
	qname = spotname.replace('NDV','SM')
	qfile = os.path.join(spotdir, qname)
	create_VRT_file(projfile, vrtfile, qfile)

	## let's import the SM quality map...
	smfile = name + '.sm'
        try:
            grass.run_command('r.in.gdal', input=vrtfile, output=smfile)
        except CalledModuleError:
            grass.fatal(_("An error occurred. Stop."))

	# some of the possible values:
	rules = [r + '\n' for r in [
	    '8 50 50 50',
	    '11 70 70 70',
	    '12 90 90 90',
	    '60 grey',
	    '155 blue',
	    '232 violet',
	    '235 red',
	    '236 brown',
	    '248 orange',
	    '251 yellow',
	    '252 green'
	    ]]
	grass.write_command('r.colors', map = smfile, rules = '-', stdin = rules)

	grass.message(_("Imported SPOT VEGETATION SM quality map <%s>.") % smfile)
	grass.message(_("Note: A snow map can be extracted by category 252 (d.rast %s cat=252)") % smfile)
	grass.message("")
	grass.message(_("Filtering NDVI map by Status Map quality layer..."))

	filtfile = "%s_filt" % name
	grass.mapcalc("$filtfile = if($smfile % 4 == 3 || ($smfile / 16) % 16 == 0, null(), $name)",
		      filtfile = filtfile, smfile = smfile, name = name)
	grass.run_command('r.colors', map = filtfile, color = 'ndvi', quiet = True)
	grass.message(_("Filtered SPOT VEGETATION NDVI map <%s>.") % filtfile)

	# write cmd history:
	grass.raster_history(smfile)
	grass.raster_history(filtfile)

    grass.message(_("Done."))
Example #36
0
def main():
    # Hard-coded parameters needed for USGS datasets
    usgs_product_dict = {
        "ned": {
            'product': 'National Elevation Dataset (NED)',
            'dataset': {
                'ned1sec': (1. / 3600, 30, 100),
                'ned13sec': (1. / 3600 / 3, 10, 30),
                'ned19sec': (1. / 3600 / 9, 3, 10)
            },
            'subset': {},
            'extent': [
                '1 x 1 degree',
                '15 x 15 minute'
            ],
            'format': 'IMG',
            'extension': 'img',
            'zip': True,
            'srs': 'wgs84',
            'srs_proj4': "+proj=longlat +ellps=GRS80 +datum=NAD83 +nodefs",
            'interpolation': 'bilinear',
            'url_split': '/'
        },
        "nlcd": {
            'product': 'National Land Cover Database (NLCD)',
            'dataset': {
                'National Land Cover Database (NLCD) - 2001': (1. / 3600, 30, 100),
                'National Land Cover Database (NLCD) - 2006': (1. / 3600, 30, 100),
                'National Land Cover Database (NLCD) - 2011': (1. / 3600, 30, 100)
            },
            'subset': {
                'Percent Developed Imperviousness',
                'Percent Tree Canopy',
                'Land Cover'
            },
            'extent': ['3 x 3 degree'],
            'format': 'GeoTIFF',
            'extension': 'tif',
            'zip': True,
            'srs': 'wgs84',
            'srs_proj4': "+proj=longlat +ellps=GRS80 +datum=NAD83 +nodefs",
            'interpolation': 'nearest',
            'url_split': '/'
        },
        "naip": {
            'product': 'USDA National Agriculture Imagery Program (NAIP)',
            'dataset': {
                'Imagery - 1 meter (NAIP)': (1. / 3600 / 27, 1, 3)},
            'subset': {},
            'extent': [
                '3.75 x 3.75 minute',
            ],
            'format': 'JPEG2000',
            'extension': 'jp2',
            'zip': False,
            'srs': 'wgs84',
            'srs_proj4': "+proj=longlat +ellps=GRS80 +datum=NAD83 +nodefs",
            'interpolation': 'nearest',
            'url_split': '/'
        },
        "lidar": {
            'product': 'Lidar Point Cloud (LPC)',
            'dataset': {
                'Lidar Point Cloud (LPC)': (1. / 3600 / 9, 3, 10)},
            'subset': {},
            'extent': [''],
            'format': 'LAS,LAZ',
            'extension': 'las,laz',
            'zip': True,
            'srs': '',
            'srs_proj4': "+proj=longlat +ellps=GRS80 +datum=NAD83 +nodefs",
            'interpolation': 'nearest',
            'url_split': '/'
        }
    }

    # Set GRASS GUI options and flags to python variables
    gui_product = options['product']

    # Variable assigned from USGS product dictionary
    nav_string = usgs_product_dict[gui_product]
    product = nav_string['product']
    product_format = nav_string['format']
    product_extensions = tuple(nav_string['extension'].split(','))
    product_is_zip = nav_string['zip']
    product_srs = nav_string['srs']
    product_proj4 = nav_string['srs_proj4']
    product_interpolation = nav_string['interpolation']
    product_url_split = nav_string['url_split']
    product_extent = nav_string['extent']
    gui_subset = None

    # Parameter assignments for each dataset
    if gui_product == 'ned':
        gui_dataset = options['ned_dataset']
        ned_api_name = ''
        if options['ned_dataset'] == 'ned1sec':
            ned_data_abbrv = 'ned_1arc_'
            ned_api_name = '1 arc-second'
        if options['ned_dataset'] == 'ned13sec':
            ned_data_abbrv = 'ned_13arc_'
            ned_api_name = '1/3 arc-second'
        if options['ned_dataset'] == 'ned19sec':
            ned_data_abbrv = 'ned_19arc_'
            ned_api_name = '1/9 arc-second'
        product_tag = product + " " + ned_api_name

    if gui_product == 'nlcd':
        gui_dataset = options['nlcd_dataset']
        if options['nlcd_dataset'] == 'nlcd2001':
            gui_dataset = 'National Land Cover Database (NLCD) - 2001'
        if options['nlcd_dataset'] == 'nlcd2006':
            gui_dataset = 'National Land Cover Database (NLCD) - 2006'
        if options['nlcd_dataset'] == 'nlcd2011':
            gui_dataset = 'National Land Cover Database (NLCD) - 2011'

        if options['nlcd_subset'] == 'landcover':
            gui_subset = 'Land Cover'
        if options['nlcd_subset'] == 'impervious':
            gui_subset = 'Percent Developed Imperviousness'
        if options['nlcd_subset'] == 'canopy':
            gui_subset = 'Percent Tree Canopy'
        product_tag = gui_dataset

    if gui_product == 'naip':
        gui_dataset = 'Imagery - 1 meter (NAIP)'
        product_tag = nav_string['product']

    has_pdal = gscript.find_program(pgm='v.in.pdal')
    if gui_product == 'lidar':
        gui_dataset = 'Lidar Point Cloud (LPC)'
        product_tag = nav_string['product']
        if not has_pdal:
            gscript.warning(_("Module v.in.pdal is missing,"
                              " any downloaded data will not be processed."))
    # Assigning further parameters from GUI
    gui_output_layer = options['output_name']
    gui_resampling_method = options['resampling_method']
    gui_i_flag = flags['i']
    gui_k_flag = flags['k']
    work_dir = options['output_directory']
    memory = options['memory']
    nprocs = options['nprocs']

    preserve_extracted_files = gui_k_flag
    use_existing_extracted_files = True
    preserve_imported_tiles = gui_k_flag
    use_existing_imported_tiles = True

    if not os.path.isdir(work_dir):
        gscript.fatal(_("Directory <{}> does not exist."
                        " Please create it.").format(work_dir))

    # Returns current units
    try:
        proj = gscript.parse_command('g.proj', flags='g')
        if gscript.locn_is_latlong():
            product_resolution = nav_string['dataset'][gui_dataset][0]
        elif float(proj['meters']) == 1:
            product_resolution = nav_string['dataset'][gui_dataset][1]
        else:
            # we assume feet
            product_resolution = nav_string['dataset'][gui_dataset][2]
    except TypeError:
        product_resolution = False
    if gui_product == 'lidar' and options['resolution']:
        product_resolution = float(options['resolution'])

    if gui_resampling_method == 'default':
        gui_resampling_method = nav_string['interpolation']
        gscript.verbose(_("The default resampling method for product {product} is {res}").format(product=gui_product,
                        res=product_interpolation))

    # Get coordinates for current GRASS computational region and convert to USGS SRS
    gregion = gscript.region()
    wgs84 = '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'
    min_coords = gscript.read_command('m.proj', coordinates=(gregion['w'], gregion['s']),
                                      proj_out=wgs84, separator='comma',
                                      flags='d')
    max_coords = gscript.read_command('m.proj', coordinates=(gregion['e'], gregion['n']),
                                      proj_out=wgs84, separator='comma',
                                      flags='d')
    min_list = min_coords.split(',')[:2]
    max_list = max_coords.split(',')[:2]
    list_bbox = min_list + max_list
    str_bbox = ",".join((str(coord) for coord in list_bbox))

    # Format variables for TNM API call
    gui_prod_str = str(product_tag)
    datasets = quote_plus(gui_prod_str)
    prod_format = quote_plus(product_format)
    prod_extent = quote_plus(product_extent[0])

    # Create TNM API URL
    base_TNM = "https://viewer.nationalmap.gov/tnmaccess/api/products?"
    datasets_TNM = "datasets={0}".format(datasets)
    bbox_TNM = "&bbox={0}".format(str_bbox)
    prod_format_TNM = "&prodFormats={0}".format(prod_format)
    TNM_API_URL = base_TNM + datasets_TNM + bbox_TNM + prod_format_TNM
    if gui_product == 'nlcd':
        TNM_API_URL += "&prodExtents={0}".format(prod_extent)
    gscript.verbose("TNM API Query URL:\t{0}".format(TNM_API_URL))

    # Query TNM API
    try_again_messge = _("Possibly, the query has timed out. Check network configuration and try again.")
    try:
        TNM_API_GET = urlopen(TNM_API_URL, timeout=12)
    except HTTPError as error:
        gscript.fatal(_(
            "HTTP(S) error from USGS TNM API:"
            " {code}: {reason} ({instructions})").format(
                reason=error.reason, code=error.code, instructions=try_again_messge))
    except (URLError, OSError, IOError) as error:
        # Catching also SSLError and potentially others which are
        # subclasses of IOError in Python 2 and of OSError in Python 3.
        gscript.fatal(_(
            "Error accessing USGS TNM API: {error} ({instructions})").format(
                error=error, instructions=try_again_messge))

    # Parse return JSON object from API query
    try:
        return_JSON = json.load(TNM_API_GET)
        if return_JSON['errors']:
            TNM_API_error = return_JSON['errors']
            api_error_msg = "TNM API Error - {0}".format(str(TNM_API_error))
            gscript.fatal(api_error_msg)
        if gui_product == 'lidar' and options['title_filter']:
            return_JSON['items'] = [item for item in return_JSON['items'] if options['title_filter'] in item['title']]
            return_JSON['total'] = len(return_JSON['items'])

    except:
        gscript.fatal(_("Unable to load USGS JSON object."))

    # Functions down_list() and exist_list() used to determine
    # existing files and those that need to be downloaded.
    def down_list():
        dwnld_url.append(TNM_file_URL)
        dwnld_size.append(TNM_file_size)
        TNM_file_titles.append(TNM_file_title)
        if product_is_zip:
            extract_zip_list.append(local_zip_path)
        if f['datasets'][0] not in dataset_name:
            if len(dataset_name) <= 1:
                dataset_name.append(str(f['datasets'][0]))

    def exist_list():
        exist_TNM_titles.append(TNM_file_title)
        exist_dwnld_url.append(TNM_file_URL)
        if product_is_zip:
            exist_zip_list.append(local_zip_path)
            extract_zip_list.append(local_zip_path)
        else:
            exist_tile_list.append(local_tile_path)

    # Assign needed parameters from returned JSON
    tile_API_count = int(return_JSON['total'])
    tiles_needed_count = 0
    size_diff_tolerance = 5
    exist_dwnld_size = 0
    if tile_API_count > 0:
        dwnld_size = []
        dwnld_url = []
        dataset_name = []
        TNM_file_titles = []
        exist_dwnld_url = []
        exist_TNM_titles = []
        exist_zip_list = []
        exist_tile_list = []
        extract_zip_list = []
        # for each file returned, assign variables to needed parameters
        for f in return_JSON['items']:
            TNM_file_title = f['title']
            TNM_file_URL = str(f['downloadURL'])
            TNM_file_size = int(f['sizeInBytes'])
            TNM_file_name = TNM_file_URL.split(product_url_split)[-1]
            if gui_product == 'ned':
                local_file_path = os.path.join(work_dir, ned_data_abbrv + TNM_file_name)
                local_zip_path = os.path.join(work_dir, ned_data_abbrv + TNM_file_name)
                local_tile_path = os.path.join(work_dir, ned_data_abbrv + TNM_file_name)
            else:
                local_file_path = os.path.join(work_dir, TNM_file_name)
                local_zip_path = os.path.join(work_dir, TNM_file_name)
                local_tile_path = os.path.join(work_dir, TNM_file_name)
            file_exists = os.path.exists(local_file_path)
            file_complete = None
            # if file exists, but is incomplete, remove file and redownload
            if file_exists:
                existing_local_file_size = os.path.getsize(local_file_path)
                # if local file is incomplete
                if abs(existing_local_file_size - TNM_file_size) > size_diff_tolerance:
                    # add file to cleanup list
                    cleanup_list.append(local_file_path)
                    # NLCD API query returns subsets that cannot be filtered before
                    # results are returned. gui_subset is used to filter results.
                    if not gui_subset:
                        tiles_needed_count += 1
                        down_list()
                    else:
                        if gui_subset in TNM_file_title:
                            tiles_needed_count += 1
                            down_list()
                        else:
                            continue
                else:
                    if not gui_subset:
                        tiles_needed_count += 1
                        exist_list()
                        exist_dwnld_size += TNM_file_size
                    else:
                        if gui_subset in TNM_file_title:
                            tiles_needed_count += 1
                            exist_list()
                            exist_dwnld_size += TNM_file_size
                        else:
                            continue
            else:
                if not gui_subset:
                    tiles_needed_count += 1
                    down_list()
                else:
                    if gui_subset in TNM_file_title:
                        tiles_needed_count += 1
                        down_list()
                        continue

    # return fatal error if API query returns no results for GUI input
    elif tile_API_count == 0:
        gscript.fatal(_("TNM API ERROR or Zero tiles available for given input parameters."))

    # number of files to be downloaded
    file_download_count = len(dwnld_url)

    # remove existing files from download lists
    for t in exist_TNM_titles:
        if t in TNM_file_titles:
            TNM_file_titles.remove(t)
    for url in exist_dwnld_url:
        if url in dwnld_url:
            dwnld_url.remove(url)

    # messages to user about status of files to be kept, removed, or downloaded
    if exist_zip_list:
        exist_msg = _("\n{0} of {1} files/archive(s) exist locally and will be used by module.").format(len(exist_zip_list), tiles_needed_count)
        gscript.message(exist_msg)
    # TODO: fix this way of reporting and merge it with the one in use
    if exist_tile_list:
        exist_msg = _("\n{0} of {1} files/archive(s) exist locally and will be used by module.").format(len(exist_tile_list), tiles_needed_count)
        gscript.message(exist_msg)
    # TODO: simply continue with whatever is needed to be done in this case
    if cleanup_list:
        cleanup_msg = _("\n{0} existing incomplete file(s) detected and removed. Run module again.").format(len(cleanup_list))
        gscript.fatal(cleanup_msg)

    # formats JSON size from bites into needed units for combined file size
    if dwnld_size:
        total_size = sum(dwnld_size)
        len_total_size = len(str(total_size))
        if 6 < len_total_size < 10:
            total_size_float = total_size * 1e-6
            total_size_str = str("{0:.2f}".format(total_size_float) + " MB")
        if len_total_size >= 10:
            total_size_float = total_size * 1e-9
            total_size_str = str("{0:.2f}".format(total_size_float) + " GB")
    else:
        total_size_str = '0'

    # Prints 'none' if all tiles available locally
    if TNM_file_titles:
        TNM_file_titles_info = "\n".join(TNM_file_titles)
    else:
        TNM_file_titles_info = 'none'

    # Formatted return for 'i' flag
    if file_download_count <= 0:
        data_info = "USGS file(s) to download: NONE"
        if gui_product == 'nlcd':
            if tile_API_count != file_download_count:
                if tiles_needed_count == 0:
                    nlcd_unavailable = "NLCD {0} data unavailable for input parameters".format(gui_subset)
                    gscript.fatal(nlcd_unavailable)
    else:
        data_info = (
            "USGS file(s) to download:",
            "-------------------------",
            "Total download size:\t{size}",
            "Tile count:\t{count}",
            "USGS SRS:\t{srs}",
            "USGS tile titles:\n{tile}",
            "-------------------------",
        )
        data_info = '\n'.join(data_info).format(size=total_size_str,
                                                count=file_download_count,
                                                srs=product_srs,
                                                tile=TNM_file_titles_info)
    print(data_info)

    if gui_i_flag:
        gscript.info(_("To download USGS data, remove <i> flag, and rerun r.in.usgs."))
        sys.exit()

    # USGS data download process
    if file_download_count <= 0:
        gscript.message(_("Extracting existing USGS Data..."))
    else:
        gscript.message(_("Downloading USGS Data..."))

    TNM_count = len(dwnld_url)
    download_count = 0
    local_tile_path_list = []
    local_zip_path_list = []
    patch_names = []

    # Download files
    for url in dwnld_url:
        # create file name by splitting name from returned url
        # add file name to local download directory
        if gui_product == 'ned':
            file_name = ned_data_abbrv + url.split(product_url_split)[-1]
            local_file_path = os.path.join(work_dir, file_name)
        else:
            file_name = url.split(product_url_split)[-1]
            local_file_path = os.path.join(work_dir, file_name)
        try:
            # download files in chunks rather than write complete files to memory
            dwnld_req = urlopen(url, timeout=12)
            download_bytes = int(dwnld_req.info()['Content-Length'])
            CHUNK = 16 * 1024
            with open(local_file_path, "wb+") as local_file:
                count = 0
                steps = int(download_bytes / CHUNK) + 1
                while True:
                    chunk = dwnld_req.read(CHUNK)
                    gscript.percent(count, steps, 10)
                    count += 1
                    if not chunk:
                        break
                    local_file.write(chunk)
                gscript.percent(1, 1, 1)
            local_file.close()
            download_count += 1
            # determine if file is a zip archive or another format
            if product_is_zip:
                local_zip_path_list.append(local_file_path)
            else:
                local_tile_path_list.append(local_file_path)
            file_complete = "Download {0} of {1}: COMPLETE".format(
                download_count, TNM_count)
            gscript.info(file_complete)
        except URLError:
            gscript.fatal(_("USGS download request has timed out. Network or formatting error."))
        except StandardError:
            cleanup_list.append(local_file_path)
            if download_count:
                file_failed = "Download {0} of {1}: FAILED".format(
                    download_count, TNM_count)
                gscript.fatal(file_failed)

    # sets already downloaded zip files or tiles to be extracted or imported
    # our pre-stats for extraction are broken, collecting stats during
    used_existing_extracted_tiles_num = 0
    removed_extracted_tiles_num = 0
    old_extracted_tiles_num = 0
    extracted_tiles_num = 0
    if exist_zip_list:
        for z in exist_zip_list:
            local_zip_path_list.append(z)
    if exist_tile_list:
        for t in exist_tile_list:
            local_tile_path_list.append(t)
    if product_is_zip:
        if file_download_count == 0:
            pass
        else:
            gscript.message("Extracting data...")
        # for each zip archive, extract needed file
        files_to_process = len(local_zip_path_list)
        for i, z in enumerate(local_zip_path_list):
            # TODO: measure only for the files being unzipped
            gscript.percent(i, files_to_process, 10)
            # Extract tiles from ZIP archives
            try:
                with zipfile.ZipFile(z, "r") as read_zip:
                    for f in read_zip.namelist():
                        if f.lower().endswith(product_extensions):
                            extracted_tile = os.path.join(work_dir, str(f))
                            remove_and_extract = True
                            if os.path.exists(extracted_tile):
                                if use_existing_extracted_files:
                                    # if the downloaded file is newer
                                    # than the extracted on, we extract
                                    if os.path.getmtime(extracted_tile) < os.path.getmtime(z):
                                        remove_and_extract = True
                                        old_extracted_tiles_num += 1
                                    else:
                                        remove_and_extract = False
                                        used_existing_extracted_tiles_num += 1
                                else:
                                    remove_and_extract = True
                                if remove_and_extract:
                                    removed_extracted_tiles_num += 1
                                    os.remove(extracted_tile)
                            if remove_and_extract:
                                extracted_tiles_num += 1
                                read_zip.extract(f, work_dir)
                if os.path.exists(extracted_tile):
                    local_tile_path_list.append(extracted_tile)
                    if not preserve_extracted_files:
                        cleanup_list.append(extracted_tile)
            except IOError as error:
                cleanup_list.append(extracted_tile)
                gscript.fatal(_(
                    "Unable to locate or extract IMG file '{filename}'"
                    " from ZIP archive '{zipname}': {error}").format(
                        filename=extracted_tile, zipname=z, error=error))
        gscript.percent(1, 1, 1)
        # TODO: do this before the extraction begins
        gscript.verbose(_("Extracted {extracted} new tiles and"
                          " used {used} existing tiles").format(
            used=used_existing_extracted_tiles_num,
            extracted=extracted_tiles_num
        ))
        if old_extracted_tiles_num:
            gscript.verbose(_("Found {removed} existing tiles older"
                              " than the corresponding downloaded archive").format(
                            removed=old_extracted_tiles_num
                            ))
        if removed_extracted_tiles_num:
            gscript.verbose(_("Removed {removed} existing tiles").format(
                            removed=removed_extracted_tiles_num
                            ))

    if gui_product == 'lidar' and not has_pdal:
        gscript.fatal(_("Module v.in.pdal is missing,"
                        " cannot process downloaded data."))

    # operations for extracted or complete files available locally
    # We are looking only for the existing maps in the current mapset,
    # but theoretically we could be getting them from other mapsets
    # on search path or from the whole location. User may also want to
    # store the individual tiles in a separate mapset.
    # The big assumption here is naming of the maps (it is a smaller
    # for the files in a dedicated download directory).
    used_existing_imported_tiles_num = 0
    imported_tiles_num = 0
    mapset = get_current_mapset()
    files_to_import = len(local_tile_path_list)

    process_list = []
    process_id_list = []
    process_count = 0
    num_tiles = len(local_tile_path_list)

    with Manager() as manager:
        results = manager.dict()
        for i, t in enumerate(local_tile_path_list):
            # create variables for use in GRASS GIS import process
            LT_file_name = os.path.basename(t)
            LT_layer_name = os.path.splitext(LT_file_name)[0]
            # we are removing the files if requested even if we don't use them
            # do not remove by default with NAIP, there are no zip files
            if gui_product != 'naip' and not preserve_extracted_files:
                cleanup_list.append(t)
            # TODO: unlike the files, we don't compare date with input
            if use_existing_imported_tiles and map_exists("raster", LT_layer_name, mapset):
                patch_names.append(LT_layer_name)
                used_existing_imported_tiles_num += 1
            else:
                in_info = _("Importing and reprojecting {name}"
                            " ({count} out of {total})...").format(
                                name=LT_file_name, count=i + 1, total=files_to_import)
                gscript.info(in_info)

                process_count += 1
                if gui_product != 'lidar':
                    process = Process(
                        name="Import-{}-{}-{}".format(process_count, i, LT_layer_name),
                        target=run_file_import, kwargs=dict(
                            identifier=i, results=results,
                            input=t, output=LT_layer_name,
                            resolution='value', resolution_value=product_resolution,
                            extent="region", resample=product_interpolation,
                            memory=memory
                        ))
                else:
                    srs = options['input_srs']
                    process = Process(
                        name="Import-{}-{}-{}".format(process_count, i, LT_layer_name),
                        target=run_lidar_import, kwargs=dict(
                            identifier=i, results=results,
                            input=t, output=LT_layer_name,
                            input_srs=srs if srs else None
                        ))
                process.start()
                process_list.append(process)
                process_id_list.append(i)

            # Wait for processes to finish when we reached the max number
            # of processes.
            if process_count == nprocs or i == num_tiles - 1:
                exitcodes = 0
                for process in process_list:
                    process.join()
                    exitcodes += process.exitcode
                if exitcodes != 0:
                    if nprocs > 1:
                        gscript.fatal(_("Parallel import and reprojection failed."
                                        " Try running with nprocs=1."))
                    else:
                        gscript.fatal(_("Import and reprojection step failed."))
                for identifier in process_id_list:
                    if "errors" in results[identifier]:
                        gscript.warning(results[identifier]["errors"])
                    else:
                        patch_names.append(results[identifier]["output"])
                        imported_tiles_num += 1
                # Empty the process list
                process_list = []
                process_id_list = []
                process_count = 0
        # no process should be left now
        assert not process_list
        assert not process_id_list
        assert not process_count

    gscript.verbose(_("Imported {imported} new tiles and"
                      " used {used} existing tiles").format(
        used=used_existing_imported_tiles_num,
        imported=imported_tiles_num
    ))

    # if control variables match and multiple files need to be patched,
    # check product resolution, run r.patch

    # v.surf.rst lidar params
    rst_params = dict(tension=25, smooth=0.1, npmin=100)

    # Check that downloaded files match expected count
    completed_tiles_count = len(local_tile_path_list)
    if completed_tiles_count == tiles_needed_count:
        if len(patch_names) > 1:
            try:
                gscript.use_temp_region()
                # set the resolution
                if product_resolution:
                    gscript.run_command('g.region', res=product_resolution, flags='a')
                if gui_product == 'naip':
                    for i in ('1', '2', '3', '4'):
                        patch_names_i = [name + '.' + i for name in patch_names]
                        output = gui_output_layer + '.' + i
                        gscript.run_command('r.patch', input=patch_names_i,
                                            output=output)
                        gscript.raster_history(output)
                elif gui_product == 'lidar':
                    gscript.run_command('v.patch', flags='nzb', input=patch_names,
                                        output=gui_output_layer)
                    gscript.run_command('v.surf.rst', input=gui_output_layer,
                                        elevation=gui_output_layer, nprocs=nprocs,
                                        **rst_params)
                else:
                    gscript.run_command('r.patch', input=patch_names,
                                        output=gui_output_layer)
                    gscript.raster_history(gui_output_layer)
                gscript.del_temp_region()
                out_info = ("Patched composite layer '{0}' added").format(gui_output_layer)
                gscript.verbose(out_info)
                # Remove files if not -k flag
                if not preserve_imported_tiles:
                    if gui_product == 'naip':
                        for i in ('1', '2', '3', '4'):
                            patch_names_i = [name + '.' + i for name in patch_names]
                            gscript.run_command('g.remove', type='raster',
                                                name=patch_names_i, flags='f')
                    elif gui_product == 'lidar':
                        gscript.run_command('g.remove', type='vector',
                                            name=patch_names + [gui_output_layer], flags='f')
                    else:
                        gscript.run_command('g.remove', type='raster',
                                            name=patch_names, flags='f')
            except CalledModuleError:
                gscript.fatal("Unable to patch tiles.")
            temp_down_count = _(
                "{0} of {1} tiles successfully imported and patched").format(
                    completed_tiles_count, tiles_needed_count)
            gscript.info(temp_down_count)
        elif len(patch_names) == 1:
            if gui_product == 'naip':
                for i in ('1', '2', '3', '4'):
                    gscript.run_command('g.rename', raster=(patch_names[0] + '.' + i, gui_output_layer + '.' + i))
            elif gui_product == 'lidar':
                if product_resolution:
                    gscript.run_command('g.region', res=product_resolution, flags='a')
                gscript.run_command('v.surf.rst', input=patch_names[0],
                                    elevation=gui_output_layer, nprocs=nprocs,
                                    **rst_params)
                if not preserve_imported_tiles:
                    gscript.run_command('g.remove', type='vector',
                                        name=patch_names[0], flags='f')
            else:
                gscript.run_command('g.rename', raster=(patch_names[0], gui_output_layer))
            temp_down_count = _("Tile successfully imported")
            gscript.info(temp_down_count)
        else:
            gscript.fatal(_("No tiles imported successfully. Nothing to patch."))
    else:
        gscript.fatal(_(
            "Error in getting or importing the data (see above). Please retry."))

    # Keep source files if 'k' flag active
    if gui_k_flag:
        src_msg = ("<k> flag selected: Source tiles remain in '{0}'").format(work_dir)
        gscript.info(src_msg)

    # set appropriate color table
    if gui_product == 'ned':
        gscript.run_command('r.colors', map=gui_output_layer, color='elevation')

    # composite NAIP
    if gui_product == 'naip':
        gscript.use_temp_region()
        gscript.run_command('g.region', raster=gui_output_layer + '.1')
        gscript.run_command('r.composite', red=gui_output_layer + '.1',
                            green=gui_output_layer + '.2', blue=gui_output_layer + '.3',
                            output=gui_output_layer)
        gscript.raster_history(gui_output_layer)
        gscript.del_temp_region()
Example #37
0
def main():
    red = options['red']
    green = options['green']
    blue = options['blue']
    brightness = options['strength']
    full = flags['f']
    preserve = flags['p']
    reset = flags['r']

    global do_mp

    if flags['s']:
        do_mp = False

    # 90 or 98? MAX value controls brightness
    # think of percent (0-100), must be positive or 0
    # must be more than "2" ?

    if full:
        for i in [red, green, blue]:
            gscript.run_command('r.colors', map=i, color='grey', quiet=True)
        sys.exit(0)

    if reset:
        for i in [red, green, blue]:
            gscript.run_command('r.colors', map=i, color='grey255', quiet=True)
        sys.exit(0)

    if not preserve:
        if do_mp:
            gscript.message(_("Processing..."))
            # set up jobs and launch them
            proc = {}
            conn = {}
            for i in [red, green, blue]:
                conn[i] = mp.Pipe()
                proc[i] = mp.Process(target=get_percentile_mp,
                                     args=(
                                         i,
                                         ['2', brightness],
                                         conn[i],
                                     ))
                proc[i].start()
            gscript.percent(1, 2, 1)

            # collect results and wait for jobs to finish
            for i in [red, green, blue]:
                output_pipe, input_pipe = conn[i]
                (v0, v1) = input_pipe.recv()
                gscript.debug('parent (%s) (%.1f, %.1f)' % (i, v0, v1))
                input_pipe.close()
                proc[i].join()
                set_colors(i, v0, v1)
            gscript.percent(1, 1, 1)
        else:
            for i in [red, green, blue]:
                gscript.message(_("Processing..."))
                (v0, v1) = get_percentile(i, ['2', brightness])
                gscript.debug("<%s>:  min=%f   max=%f" % (i, v0, v1))
                set_colors(i, v0, v1)

    else:
        all_max = 0
        all_min = 999999

        if do_mp:
            gscript.message(_("Processing..."))
            # set up jobs and launch jobs
            proc = {}
            conn = {}
            for i in [red, green, blue]:
                conn[i] = mp.Pipe()
                proc[i] = mp.Process(target=get_percentile_mp,
                                     args=(
                                         i,
                                         ['2', brightness],
                                         conn[i],
                                     ))
                proc[i].start()
            gscript.percent(1, 2, 1)

            # collect results and wait for jobs to finish
            for i in [red, green, blue]:
                output_pipe, input_pipe = conn[i]
                (v0, v1) = input_pipe.recv()
                gscript.debug('parent (%s) (%.1f, %.1f)' % (i, v0, v1))
                input_pipe.close()
                proc[i].join()
                all_min = min(all_min, v0)
                all_max = max(all_max, v1)
            gscript.percent(1, 1, 1)
        else:
            for i in [red, green, blue]:
                gscript.message(_("Processing..."))
                (v0, v1) = get_percentile(i, ['2', brightness])
                gscript.debug("<%s>:  min=%f   max=%f" % (i, v0, v1))
                all_min = min(all_min, v0)
                all_max = max(all_max, v1)

        gscript.debug("all_min=%f   all_max=%f" % (all_min, all_max))
        for i in [red, green, blue]:
            set_colors(i, all_min, all_max)

    # write cmd history:
    mapset = gscript.gisenv()['MAPSET']
    for i in [red, green, blue]:
        if gscript.find_file(i)['mapset'] == mapset:
            gscript.raster_history(i)
Example #38
0
def main():
    global temp_dist, temp_val

    input = options['input']
    output = options['output']
    radius = float(options['radius'])
    metric = options['metric']
    old = options['old']
    new = options['new']
    mapunits = flags['m']

    tmp = str(os.getpid())

    temp_dist = "r.grow.tmp.%s.dist" % tmp
    
    shrink = False
    if radius < 0.0:
        shrink = True
        radius = -radius

    if new == '' and shrink == False:
        temp_val = "r.grow.tmp.%s.val" % tmp
        new = temp_val
    else:
        temp_val = None

    if old == '':
        old = input

    if not mapunits:
        kv = grass.region()
        scale = math.sqrt(float(kv['nsres']) * float(kv['ewres']))
        radius *= scale

    if metric == 'euclidean':
        metric = 'squared'
        radius = radius * radius

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

    if shrink == False:
        try:
            grass.run_command('r.grow.distance', input=input, metric=metric,
                              distance=temp_dist, value=temp_val)
        except CalledModuleError:
            grass.fatal(_("Growing failed. Removing temporary maps."))

        grass.mapcalc(
            "$output = if(!isnull($input),$old,if($dist < $radius,$new,null()))",
            output=output, input=input, radius=radius,
            old=old, new=new, dist=temp_dist)
    else:
        # shrink
        try:
            grass.run_command('r.grow.distance', input=input, metric=metric,
                              distance=temp_dist, value=temp_val, flags='n')
        except CalledModuleError:
            grass.fatal(_("Shrinking failed. Removing temporary maps."))

        grass.mapcalc(
            "$output = if($dist < $radius,null(),$old)",
            output=output, radius=radius, old=old, dist=temp_dist)

    grass.run_command('r.colors', map=output, raster=input)

    # write cmd history:
    grass.raster_history(output)
Example #39
0
def main():
    name = options["output"]
    type = options["type"]
    dip = float(options["dip"])
    az = float(options["azimuth"])
    try:
        ea = float(options["easting"])
        no = float(options["northing"])
    except ValueError:
        try:
            ea = float(gscript.utils.float_or_dms(options["easting"]))
            no = float(gscript.utils.float_or_dms(options["northing"]))
        except Exception:
            gscript.fatal(_("Input coordinates seems to be invalid"))
    el = float(options["elevation"])

    # reg = gscript.region()

    # Test input values
    if abs(dip) >= 90:
        gscript.fatal(_("dip must be between -90 and 90."))

    if az < 0 or az >= 360:
        gscript.fatal(_("azimuth must be between 0 and 360"))

    # now the actual algorithm
    az_r = math.radians(-az)
    sinaz = math.sin(az_r)
    cosaz = math.cos(az_r)

    dip_r = math.radians(-dip)
    tandip = math.tan(dip_r)

    kx = sinaz * tandip
    ky = cosaz * tandip
    kz = el - ea * sinaz * tandip - no * cosaz * tandip

    if type == "CELL":
        round = "round"
        dtype = "int"
    elif type == "FCELL":
        round = ""
        dtype = "float"
    else:
        round = ""
        dtype = "double"

    gscript.mapcalc(
        "$name = $type($round(x() * $kx + y() * $ky + $kz))",
        name=name,
        type=dtype,
        round=round,
        kx=kx,
        ky=ky,
        kz=kz,
    )

    gscript.run_command("r.support", map=name, history="")
    gscript.raster_history(name)

    gscript.message(_("Done."))
    t = string.Template("Raster map <$name> generated by r.plane "
                        "at point $ea E, $no N, elevation $el with dip = $dip"
                        " degrees and aspect = $az degrees ccw from north.")
    gscript.message(
        t.substitute(name=name, ea=ea, no=no, el=el, dip=dip, az=az))
Example #40
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)
Example #41
0
def main():
    options, flags = gs.parser()
    simulated = options["simulated"]
    original = options["original"]
    reference = options["reference"]
    kappa = options["kappa"]
    kappasimulation = options["kappasimulation"]
    quantity_disagreement = options["quantity_disagreement"]
    allocation_disagreement = options["allocation_disagreement"]
    quantity_disagreement_basename = options["quantity_disagreement_basename"]
    allocation_disagreement_basename = options[
        "allocation_disagreement_basename"]
    input_region = options["region"]
    nprocs = int(options["nprocs"])

    current = gs.region()
    region = gs.parse_command("g.region", flags="pug", region=input_region)
    regions = []
    for row in range(int(region["rows"])):
        for col in range(int(region["cols"])):
            s = float(region["s"]) + row * float(region["nsres"])
            n = float(region["s"]) + (row + 1) * float(region["nsres"])
            w = float(region["w"]) + col * float(region["ewres"])
            e = float(region["w"]) + (col + 1) * float(region["ewres"])
            regions.append({
                "n": n,
                "s": s,
                "w": w,
                "e": e,
                "nsres": float(current["nsres"]),
                "ewres": float(current["ewres"]),
            })
    results = []
    params = []
    for each in regions:
        if original:
            params.append({
                "region": each,
                "simulated": simulated,
                "reference": reference,
                "original": original,
            })
        else:
            params.append({
                "region": each,
                "simulated": simulated,
                "reference": reference
            })

    with Pool(processes=nprocs) as pool:
        results = pool.map_async(compute, params).get()
    outputs = {}
    if kappa:
        outputs["kappa"] = {"name": kappa, "param": "kappa", "inp": ""}
    if kappasimulation:
        outputs["kappasim"] = {
            "name": kappasimulation,
            "param": "kappasimulation",
            "inp": "",
        }
    if quantity_disagreement:
        outputs["quantity_disagreement"] = {
            "name": quantity_disagreement,
            "param": "total_quantity",
            "inp": "",
        }
    if allocation_disagreement:
        outputs["allocation_disagreement"] = {
            "name": allocation_disagreement,
            "param": "total_allocation",
            "inp": "",
        }
    env = os.environ.copy()
    env["GRASS_REGION"] = gs.region_env(region=input_region)
    for r in results:
        for key in r.keys():
            if allocation_disagreement_basename and "allocation_class_" in key:
                cl = key.replace("allocation_class_", "")
                if cl not in outputs:
                    outputs[cl] = {
                        "name": allocation_disagreement_basename + "_" + cl,
                        "param": key,
                        "inp": "",
                    }
            if quantity_disagreement_basename and "quantity_class_" in key:
                cl = key.replace("quantity_class_", "")
                if cl not in outputs:
                    outputs[cl] = {
                        "name": quantity_disagreement_basename + "_" + cl,
                        "param": key,
                        "inp": "",
                    }
        for k in outputs:
            if outputs[k]["param"] in r and r[outputs[k]["param"]] is not None:
                outputs[k][
                    "inp"] += f"{r['e']},{r['n']},{r[outputs[k]['param']]}\n"
    for k in outputs:
        gs.write_command(
            "r.in.xyz",
            input="-",
            stdin=outputs[k]["inp"],
            output=outputs[k]["name"],
            method="mean",
            separator="comma",
            env=env,
            quiet=True,
        )
        gs.raster_history(outputs[k]["name"])
Example #42
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)
Example #43
0
def main():
    global tile, tmpdir, in_temp

    in_temp = False

    # to support SRTM water body
    swbd = False

    input = options["input"]
    output = options["output"]
    one = flags["1"]

    # are we in LatLong location?
    s = grass.read_command("g.proj", flags="j")
    kv = grass.parse_key_val(s)
    if "+proj" not in kv.keys() or kv["+proj"] != "longlat":
        grass.fatal(_("This module only operates in LatLong locations"))

    # use these from now on:
    infile = input
    while infile[-4:].lower() in [".hgt", ".zip", ".raw"]:
        infile = infile[:-4]
    (fdir, tile) = os.path.split(infile)

    if not output:
        tileout = tile
    else:
        tileout = output

    if ".hgt" in input:
        suff = ".hgt"
    else:
        suff = ".raw"
        swbd = True

    zipfile = "{im}{su}.zip".format(im=infile, su=suff)
    hgtfile = "{im}{su}".format(im=infile, su=suff)

    if os.path.isfile(zipfile):
        # really a ZIP file?
        if not zfile.is_zipfile(zipfile):
            grass.fatal(_("'%s' does not appear to be a valid zip file.") % zipfile)

        is_zip = True
    elif os.path.isfile(hgtfile):
        # try and see if it's already unzipped
        is_zip = False
    else:
        grass.fatal(_("File '%s' or '%s' not found") % (zipfile, hgtfile))

    # make a temporary directory
    tmpdir = grass.tempfile()
    grass.try_remove(tmpdir)
    os.mkdir(tmpdir)
    if is_zip:
        shutil.copyfile(
            zipfile, os.path.join(tmpdir, "{im}{su}.zip".format(im=tile, su=suff))
        )
    else:
        shutil.copyfile(
            hgtfile, os.path.join(tmpdir, "{im}{su}".format(im=tile[:7], su=suff))
        )
    # change to temporary directory
    os.chdir(tmpdir)
    in_temp = True

    zipfile = "{im}{su}.zip".format(im=tile, su=suff)
    hgtfile = "{im}{su}".format(im=tile[:7], su=suff)

    bilfile = tile + ".bil"

    if is_zip:
        # unzip & rename data file:
        grass.message(_("Extracting '%s'...") % infile)
        try:
            zf = zfile.ZipFile(zipfile)
            zf.extractall()
        except:
            grass.fatal(_("Unable to unzip file."))

    grass.message(_("Converting input file to BIL..."))
    os.rename(hgtfile, bilfile)

    north = tile[0]
    ll_latitude = int(tile[1:3])
    east = tile[3]
    ll_longitude = int(tile[4:7])

    # are we on the southern hemisphere? If yes, make LATITUDE negative.
    if north == "S":
        ll_latitude *= -1

    # are we west of Greenwich? If yes, make LONGITUDE negative.
    if east == "W":
        ll_longitude *= -1

    # Calculate Upper Left from Lower Left
    ulxmap = "%.1f" % ll_longitude
    # SRTM90 tile size is 1 deg:
    ulymap = "%.1f" % (ll_latitude + 1)

    if not one:
        tmpl = tmpl3sec
    elif swbd:
        grass.message(_("Attempting to import 1-arcsec SWBD data"))
        tmpl = swbd1sec
    else:
        grass.message(_("Attempting to import 1-arcsec data"))
        tmpl = tmpl1sec

    header = tmpl % (ulxmap, ulymap)
    hdrfile = tile + ".hdr"
    outf = open(hdrfile, "w")
    outf.write(header)
    outf.close()

    # create prj file: To be precise, we would need EGS96! But who really cares...
    prjfile = tile + ".prj"
    outf = open(prjfile, "w")
    outf.write(proj)
    outf.close()

    try:
        grass.run_command("r.in.gdal", input=bilfile, out=tileout)
    except:
        grass.fatal(_("Unable to import data"))

    # nice color table
    if not swbd:
        grass.run_command("r.colors", map=tileout, color="srtm")

    # write cmd history:
    grass.raster_history(tileout)

    grass.message(_("Done: generated map ") + tileout)
    grass.message(
        _("(Note: Holes in the data can be closed with 'r.fillnulls' using splines)")
    )
Example #44
0
def main():
    global temp_dist, temp_val

    input = options['input']
    radius = float(options['radius'])
    metric = options['metric']
    old = options['old']
    new = options['new']
    mapunits = flags['m']

    tmp = str(os.getpid())

    temp_dist = "r.grow.tmp.%s.dist" % tmp

    shrink = False
    if radius < 0.0:
        shrink = True
        radius = -radius

    if new == '' and not shrink:
        temp_val = "r.grow.tmp.%s.val" % tmp
        new = '"%s"' % temp_val
    else:
        temp_val = None

    if old == '':
        old = '"%s"' % input

    if not mapunits:
        kv = grass.region()
        scale = math.sqrt(float(kv['nsres']) * float(kv['ewres']))
        radius *= scale

    if metric == 'euclidean':
        metric = 'squared'
        radius = radius * radius

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

    # Workaround for r.mapcalc bug #3475
    # Mapcalc will fail if output is a fully qualified map name
    out_name = options['output'].split('@')
    if len(out_name) == 2:
        if out_name[1] != grass.gisenv()['MAPSET']:
            grass.fatal(_("Output can be written only to the current mapset"))
        output = out_name[0]
    else:
        output = out_name[0]

    if not shrink:
        try:
            grass.run_command('r.grow.distance', input=input, metric=metric,
                              distance=temp_dist, value=temp_val)
        except CalledModuleError:
            grass.fatal(_("Growing failed. Removing temporary maps."))

        grass.mapcalc(
            '$output = if(!isnull("$input"),$old,if($dist < $radius,$new,null()))',
            output=output, input=input, radius=radius,
            old=old, new=new, dist=temp_dist)
    else:
        # shrink
        try:
            grass.run_command('r.grow.distance', input=input, metric=metric,
                              distance=temp_dist, value=temp_val, flags='n')
        except CalledModuleError:
            grass.fatal(_("Shrinking failed. Removing temporary maps."))

        grass.mapcalc(
            "$output = if(isnull($dist), $old, if($dist < $radius,null(),$old))",
            output=output, radius=radius, old=old, dist=temp_dist)

    grass.run_command('r.colors', map=output, raster=input)

    # write cmd history:
    grass.raster_history(output)
Example #45
0
def main():
    """Do the main work"""

    # set numpy printing options
    np.set_printoptions(formatter={"float": lambda x: "{0:0.2f}".format(x)})

    # ==========================================================================
    # Input data
    # ==========================================================================
    # Required
    r_output = options["output"]
    r_dsm = options["input"]
    dsm_type = grass.parse_command("r.info", map=r_dsm, flags="g")["datatype"]

    # Test if DSM exist
    gfile_dsm = grass.find_file(name=r_dsm, element="cell")
    if not gfile_dsm["file"]:
        grass.fatal("Raster map <{}> not found".format(r_dsm))

    # Exposure settings
    v_source = options["sampling_points"]
    r_source = options["source"]
    source_cat = options["sourcecat"]
    r_weights = options["weights"]

    # test if source vector map exist and contains points
    if v_source:
        gfile_vsource = grass.find_file(name=v_source, element="vector")
        if not gfile_vsource["file"]:
            grass.fatal("Vector map <{}> not found".format(v_source))
        if not grass.vector.vector_info_topo(v_source, layer=1)["points"] > 0:
            grass.fatal("Vector map <{}> does not contain any points.".format(
                v_source))

    if r_source:
        gfile_rsource = grass.find_file(name=r_source, element="cell")
        if not gfile_rsource["file"]:
            grass.fatal("Raster map <{}> not found".format(r_source))

        # if source_cat is set, check that r_source is CELL
        source_datatype = grass.parse_command("r.info",
                                              map=r_source,
                                              flags="g")["datatype"]

        if source_cat != "*" and source_datatype != "CELL":
            grass.fatal(
                "The raster map <%s> must be integer (CELL type) in order to \
                use the 'sourcecat' parameter" % r_source)

    if r_weights:
        gfile_weights = grass.find_file(name=r_weights, element="cell")
        if not gfile_weights["file"]:
            grass.fatal("Raster map <{}> not found".format(r_weights))

    # Viewshed settings
    range_inp = float(options["range"])
    v_elevation = float(options["observer_elevation"])
    b_1 = float(options["b1_distance"])
    pfunction = options["function"]
    refr_coeff = float(options["refraction_coeff"])
    flagstring = ""
    if flags["r"]:
        flagstring += "r"
    if flags["c"]:
        flagstring += "c"

    # test values
    if v_elevation < 0.0:
        grass.fatal("Observer elevation must be larger than or equal to 0.0.")

    if range_inp <= 0.0 and range_inp != -1:
        grass.fatal("Exposure range must be larger than 0.0.")

    if pfunction == "Fuzzy_viewshed" and range_inp == -1:
        grass.fatal("Exposure range cannot be \
            infinity for fuzzy viewshed approch.")

    if pfunction == "Fuzzy_viewshed" and b_1 > range_inp:
        grass.fatal("Exposure range must be larger than radius around \
            the viewpoint where clarity is perfect.")

    # Sampling settings
    source_sample_density = float(options["sample_density"])
    seed = options["seed"]

    if not seed:  # if seed is not set, set it to process number
        seed = os.getpid()

    # Optional
    cores = int(options["nprocs"])
    memory = int(options["memory"])

    # ==========================================================================
    # Region settings
    # ==========================================================================
    # check that location is not in lat/long
    if grass.locn_is_latlong():
        grass.fatal("The analysis is not available for lat/long coordinates.")

    # get comp. region parameters
    reg = Region()

    # check that NSRES equals EWRES
    if abs(reg.ewres - reg.nsres) > 1e-6:
        grass.fatal("Variable north-south and east-west 2D grid resolution \
            is not supported")

    # adjust exposure range as a multiplicate of region resolution
    # if infinite, set exposure range to the max of region size
    if range_inp != -1:
        multiplicate = math.floor(range_inp / reg.nsres)
        exp_range = multiplicate * reg.nsres
    else:
        range_inf = max(reg.north - reg.south, reg.east - reg.west)
        multiplicate = math.floor(range_inf / reg.nsres)
        exp_range = multiplicate * reg.nsres

    if RasterRow("MASK", Mapset().name).exist():
        grass.warning("Current MASK is temporarily renamed.")
        unset_mask()

    # ==========================================================================
    # Random sample exposure source with target points T
    # ==========================================================================
    if v_source:
        # go for using input vector map as sampling points
        v_source_sample = v_source
        grass.verbose("Using sampling points from input vector map")

    else:
        # go for sampling

        # min. distance between samples set to half of region resolution
        # (issue in r.random.cells)
        sample_distance = reg.nsres / 2
        v_source_sample = sample_raster_with_points(
            r_source,
            source_cat,
            source_sample_density,
            sample_distance,
            "{}_rand_pts_vect".format(TEMPNAME),
            seed,
        )

    # ==========================================================================
    # Get coordinates and attributes of target points T
    # ==========================================================================
    # Prepare a list of maps to extract attributes from
    # DSM values
    attr_map_list = [r_dsm]

    if pfunction in ["Solid_angle", "Visual_magnitude"]:
        grass.verbose("Precomputing parameter maps...")

    # Precompute values A, B, C, D for solid angle function
    # using moving window [row, col]
    if pfunction == "Solid_angle":
        r_a_z = "{}_A_z".format(TEMPNAME)
        r_b_z = "{}_B_z".format(TEMPNAME)
        r_c_z = "{}_C_z".format(TEMPNAME)
        r_d_z = "{}_D_z".format(TEMPNAME)

        expr = ";".join([
            "$outmap_A = ($inmap[0, 0] + \
                          $inmap[0, -1] + \
                          $inmap[1, -1] + \
                          $inmap[1, 0]) / 4",
            "$outmap_B = ($inmap[-1, 0] + \
                          $inmap[-1, -1] + \
                          $inmap[0, -1] + \
                          $inmap[0, 0]) / 4",
            "$outmap_C = ($inmap[-1, 1] + \
                          $inmap[-1, 0] + \
                          $inmap[0, 0] + \
                          $inmap[0, 1]) / 4",
            "$outmap_D = ($inmap[0, 1] + \
                          $inmap[0, 0] + \
                          $inmap[1, 0] + \
                          $inmap[1, 1]) / 4",
        ])
        grass.mapcalc(
            expr,
            inmap=r_dsm,
            outmap_A=r_a_z,
            outmap_B=r_b_z,
            outmap_C=r_c_z,
            outmap_D=r_d_z,
            overwrite=True,
            quiet=grass.verbosity() <= 1,
        )

        attr_map_list.extend([r_a_z, r_b_z, r_c_z, r_d_z])

    # Precompute values slopes in e-w direction, n-s direction
    # as atan(dz/dx) (e-w direction), atan(dz/dy) (n-s direction)
    # using moving window [row, col]
    elif pfunction == "Visual_magnitude":

        r_slope_ew = "{}_slope_ew".format(TEMPNAME)
        r_slope_ns = "{}_slope_ns".format(TEMPNAME)

        expr = ";".join([
            "$outmap_ew = atan((sqrt(2) * $inmap[-1, 1] + \
                          2 * $inmap[0, 1] + \
                          sqrt(2) * $inmap[1, 1] - \
                          sqrt(2) * $inmap[-1, -1] - \
                          2 * $inmap[0, -1] - \
                          sqrt(2) * $inmap[1, -1]) / \
                          (8 * $w_ew))",
            "$outmap_ns = atan((sqrt(2) * $inmap[-1, -1] + \
                          2 * $inmap[-1, 0] + \
                          sqrt(2) * $inmap[-1, 1] - \
                          sqrt(2) * $inmap[1, -1] - \
                          2 * $inmap[1, 0] - \
                          sqrt(2) * $inmap[1, 1]) / \
                          (8 * $w_ns))",
        ])

        grass.mapcalc(
            expr,
            inmap=r_dsm,
            outmap_ew=r_slope_ew,
            outmap_ns=r_slope_ns,
            w_ew=reg.ewres,
            w_ns=reg.nsres,
            overwrite=True,
            quiet=grass.verbosity() <= 1,
        )

        attr_map_list.extend([r_slope_ew, r_slope_ns])

    # Use viewshed weights if provided
    if r_weights:
        attr_map_list.append(r_weights)

    # Extract attribute values
    target_pts_grass = grass.read_command(
        "r.what",
        flags="v",
        map=attr_map_list,
        points=v_source_sample,
        separator="|",
        null_value="*",
        quiet=True,
    )

    # columns to use depending on parametrization function
    usecols = list(range(0, 4 + len(attr_map_list)))
    usecols.remove(3)  # skip 3rd column - site_name

    # convert coordinates and attributes of target points T to numpy array
    target_pts_np = txt2numpy(
        target_pts_grass,
        sep="|",
        names=None,
        null_value="*",
        usecols=usecols,
        structured=False,
    )

    # if one point only - 0D array which cannot be used in iteration
    if target_pts_np.ndim == 1:
        target_pts_np = target_pts_np.reshape(1, -1)

    target_pts_np = target_pts_np[~np.isnan(target_pts_np).any(axis=1)]

    no_points = target_pts_np.shape[0]

    # if viewshed weights not set by flag - set weight to 1 for all pts
    if not r_weights:
        weights_np = np.ones((no_points, 1))
        target_pts_np = np.hstack((target_pts_np, weights_np))

    grass.debug("target_pts_np: {}".format(target_pts_np))

    # ==========================================================================
    # Calculate weighted parametrised cummulative viewshed
    # by iterating over target points T
    # ==========================================================================
    grass.verbose("Calculating partial viewsheds...")

    # Parametrisation function
    if pfunction == "Solid_angle":
        parametrise_viewshed = solid_angle_reverse

    elif pfunction == "Distance_decay":
        parametrise_viewshed = distance_decay_reverse

    elif pfunction == "Fuzzy_viewshed":
        parametrise_viewshed = fuzzy_viewshed_reverse

    elif pfunction == "Visual_magnitude":
        parametrise_viewshed = visual_magnitude_reverse

    else:
        parametrise_viewshed = binary

    # Collect variables that will be used in do_it_all() into a dictionary
    global_vars = {
        "region": reg,
        "range": exp_range,
        "param_viewshed": parametrise_viewshed,
        "observer_elevation": v_elevation,
        "b_1": b_1,
        "memory": memory,
        "refr_coeff": refr_coeff,
        "flagstring": flagstring,
        "r_dsm": r_dsm,
        "dsm_type": dsm_type,
        "cores": cores,
        "tempname": TEMPNAME,
    }

    # Split target points to chunks for each core
    target_pnts = np.array_split(target_pts_np, cores)

    # Combine each chunk with dictionary
    combo = list(zip(itertools.repeat(global_vars), target_pnts))

    # Calculate partial cummulative viewshed
    with Pool(cores) as pool:
        np_sum = pool.starmap(do_it_all, combo)
        pool.close()
        pool.join()

    # We should probably use nansum here?
    all_nan = np.all(np.isnan(np_sum), axis=0)
    np_sum = np.nansum(np_sum, axis=0, dtype=np.single)
    np_sum[all_nan] = np.nan

    grass.verbose("Writing final result and cleaning up...")

    # Restore original computational region
    reg.read()
    reg.set_current()
    reg.set_raster_region()

    # Convert numpy array of cummulative viewshed to raster
    numpy2raster(np_sum, mtype="FCELL", rastname=r_output, overwrite=True)

    # Remove temporary files and reset mask if needed
    cleanup()

    # Set raster history to output raster
    grass.raster_history(r_output, overwrite=True)
    grass.run_command(
        "r.support",
        overwrite=True,
        map=r_output,
        title="Visual exposure index as {}".format(pfunction.replace("_",
                                                                     " ")),
        description="generated by r.viewshed.exposure",
        units="Index value",
        quiet=True,
    )
Example #46
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))
Example #47
0
def main():
    global tile, tmpdir, in_temp

    in_temp = False

    input = options['input']
    output = options['output']
    one = flags['1']

    # are we in LatLong location?
    s = grass.read_command("g.proj", flags='j')
    kv = grass.parse_key_val(s)
    if kv['+proj'] != 'longlat':
        grass.fatal(_("This module only operates in LatLong locations"))

    # use these from now on:
    infile = input
    while infile[-4:].lower() in ['.hgt', '.zip']:
        infile = infile[:-4]
    (fdir, tile) = os.path.split(infile)

    if not output:
        tileout = tile
    else:
        tileout = output

    zipfile = infile + ".hgt.zip"
    hgtfile = os.path.join(fdir, tile[:7] + ".hgt")
    if os.path.isfile(zipfile):
        # check if we have unzip
        if not grass.find_program('unzip'):
            grass.fatal(
                _('The "unzip" program is required, please install it first'))

        # really a ZIP file?
        # make it quiet in a safe way (just in case -qq isn't portable)
        tenv = os.environ.copy()
        tenv['UNZIP'] = '-qq'
        if grass.call(['unzip', '-t', zipfile], env=tenv) != 0:
            grass.fatal(
                _("'%s' does not appear to be a valid zip file.") % zipfile)

        is_zip = True
    elif os.path.isfile(hgtfile):
        # try and see if it's already unzipped
        is_zip = False
    else:
        grass.fatal(_("File '%s' or '%s' not found") % (zipfile, hgtfile))

    # make a temporary directory
    tmpdir = grass.tempfile()
    grass.try_remove(tmpdir)
    os.mkdir(tmpdir)

    if is_zip:
        shutil.copyfile(zipfile, os.path.join(tmpdir, tile + ".hgt.zip"))
    else:
        shutil.copyfile(hgtfile, os.path.join(tmpdir, tile + ".hgt"))

    # change to temporary directory
    os.chdir(tmpdir)
    in_temp = True

    zipfile = tile + ".hgt.zip"
    hgtfile = tile[:7] + ".hgt"
    bilfile = tile + ".bil"

    if is_zip:
        # unzip & rename data file:
        grass.message(_("Extracting '%s'...") % infile)
        if grass.call(['unzip', zipfile], env=tenv) != 0:
            grass.fatal(_("Unable to unzip file."))

    grass.message(_("Converting input file to BIL..."))
    os.rename(hgtfile, bilfile)

    north = tile[0]
    ll_latitude = int(tile[1:3])
    east = tile[3]
    ll_longitude = int(tile[4:7])

    # are we on the southern hemisphere? If yes, make LATITUDE negative.
    if north == "S":
        ll_latitude *= -1

    # are we west of Greenwich? If yes, make LONGITUDE negative.
    if east == "W":
        ll_longitude *= -1

    # Calculate Upper Left from Lower Left
    ulxmap = "%.1f" % ll_longitude
    # SRTM90 tile size is 1 deg:
    ulymap = "%.1f" % (ll_latitude + 1)

    if not one:
        tmpl = tmpl3sec
    else:
        grass.message(_("Attempting to import 1-arcsec data."))
        tmpl = tmpl1sec

    header = tmpl % (ulxmap, ulymap)
    hdrfile = tile + '.hdr'
    outf = file(hdrfile, 'w')
    outf.write(header)
    outf.close()

    # create prj file: To be precise, we would need EGS96! But who really cares...
    prjfile = tile + '.prj'
    outf = file(prjfile, 'w')
    outf.write(proj)
    outf.close()

    try:
        grass.run_command('r.in.gdal', input=bilfile, out=tileout)
    except:
        grass.fatal(_("Unable to import data"))

    # nice color table
    grass.run_command('r.colors', map=tileout, color='srtm')

    # write cmd history:
    grass.raster_history(tileout)

    grass.message(_("Done: generated map ") + tileout)
    grass.message(
        _("(Note: Holes in the data can be closed with 'r.fillnulls' using splines)"
          ))