Пример #1
0
def classify_recreation_component(component, rules, output_name):
    """
    Recode an input recreation component based on given rules

    To Do:

    - Potentially, test range of input recreation component, i.e. ranging in
      [0,1]

    Parameters
    ----------
    component :
        Name of input raster map

    rules :
        Rules for r.recode

    output_name :
        Name for output raster map

    Returns
    -------
        Does not return any value

    Examples
    --------
    ...

    """
    r.recode(input=component, rules="-", stdin=rules, output=output_name)
Пример #2
0
def recode_map(raster, rules, colors, output):
    """Scores a raster map based on a set of category recoding rules.

    This is a wrapper around r.recode

    Parameters
    ----------
    raster :
        Name of input raster map

    rules :
        Rules for r.recode

    colors :
        Color rules for r.colors

    output :
        Name of output raster map

    Returns
    -------
        Does not return any value

    Examples
    --------
    ...
    """
    msg = "Setting NULL cells in {name} map to 0"
    msg = msg.format(name=raster)
    grass.debug(_(msg))

    # ------------------------------------------
    r.null(map=raster, null=0)  # Set NULLs to 0
    msg = "To Do: confirm if setting the '{raster}' map's NULL cells to 0 is right"
    msg = msg.format(raster=raster)
    grass.debug(_(msg))
    # Is this right?
    # ------------------------------------------

    r.recode(input=raster, rules=rules, output=output)

    r.colors(map=output, rules="-", stdin=SCORE_COLORS, quiet=True)

    grass.verbose(_("Scored map {name}:".format(name=raster)))
Пример #3
0
def main():

    elevation = options['elevation']
    slope = options['slope']
    flat_thres = float(options['flat_thres'])
    curv_thres = float(options['curv_thres'])
    filter_size = int(options['filter_size'])
    counting_size = int(options['counting_size'])
    nclasses = int(options['classes'])
    texture = options['texture']
    convexity = options['convexity']
    concavity = options['concavity']
    features = options['features']

    # remove mapset from output name in case of overwriting existing map
    texture = texture.split('@')[0]
    convexity = convexity.split('@')[0]
    concavity = concavity.split('@')[0]
    features = features.split('@')[0]

    # store current region settings
    global current_reg
    current_reg = parse_key_val(g.region(flags='pg', stdout_=PIPE).outputs.stdout)
    del current_reg['projection']
    del current_reg['zone']
    del current_reg['cells']

    # check for existing mask and backup if found
    global mask_test
    mask_test = gs.list_grouped(
        type='rast', pattern='MASK')[gs.gisenv()['MAPSET']]
    if mask_test:
        global original_mask
        original_mask = temp_map('tmp_original_mask')
        g.copy(raster=['MASK', original_mask])

    # error checking
    if flat_thres < 0:
        gs.fatal('Parameter thres cannot be negative')

    if filter_size % 2 == 0 or counting_size % 2 == 0:
        gs.fatal(
            'Filter or counting windows require an odd-numbered window size')

    if filter_size >= counting_size:
        gs.fatal(
            'Filter size needs to be smaller than the counting window size')
    
    if features != '' and slope == '':
        gs.fatal('Need to supply a slope raster in order to produce the terrain classification')
                
    # Terrain Surface Texture -------------------------------------------------
    # smooth the dem
    gs.message("Calculating terrain surface texture...")
    gs.message(
        "1. Smoothing input DEM with a {n}x{n} median filter...".format(
            n=filter_size))
    filtered_dem = temp_map('tmp_filtered_dem')
    gs.run_command("r.neighbors", input = elevation, method = "median",
                    size = filter_size, output = filtered_dem, flags='c',
                    quiet=True)

    # extract the pits and peaks based on the threshold
    pitpeaks = temp_map('tmp_pitpeaks')
    gs.message("2. Extracting pits and peaks with difference > thres...")
    r.mapcalc(expression='{x} = if ( abs({dem}-{median})>{thres}, 1, 0)'.format(
                x=pitpeaks, dem=elevation, thres=flat_thres, median=filtered_dem),
                quiet=True)

    # calculate density of pits and peaks
    gs.message("3. Using resampling filter to create terrain texture...")
    window_radius = (counting_size-1)/2
    y_radius = float(current_reg['ewres'])*window_radius
    x_radius = float(current_reg['nsres'])*window_radius
    resample = temp_map('tmp_density')
    r.resamp_filter(input=pitpeaks, output=resample, filter=['bartlett','gauss'],
                    radius=[x_radius,y_radius], quiet=True)

    # convert to percentage
    gs.message("4. Converting to percentage...")
    r.mask(raster=elevation, overwrite=True, quiet=True)
    r.mapcalc(expression='{x} = float({y} * 100)'.format(x=texture, y=resample),
               quiet=True)
    r.mask(flags='r', quiet=True)
    r.colors(map=texture, color='haxby', quiet=True)

    # Terrain convexity/concavity ---------------------------------------------
    # surface curvature using lacplacian filter
    gs.message("Calculating terrain convexity and concavity...")
    gs.message("1. Calculating terrain curvature using laplacian filter...")
    
    # grow the map to remove border effects and run laplacian filter
    dem_grown = temp_map('tmp_elevation_grown')
    laplacian = temp_map('tmp_laplacian')
    g.region(n=float(current_reg['n']) + (float(current_reg['nsres']) * filter_size),
             s=float(current_reg['s']) - (float(current_reg['nsres']) * filter_size),
             w=float(current_reg['w']) - (float(current_reg['ewres']) * filter_size),
             e=float(current_reg['e']) + (float(current_reg['ewres']) * filter_size))

    r.grow(input=elevation, output=dem_grown, radius=filter_size, quiet=True)
    r.mfilter(
        input=dem_grown, output=laplacian,
        filter=string_to_rules(laplacian_matrix(filter_size)), quiet=True)

    # extract convex and concave pixels
    gs.message("2. Extracting convexities and concavities...")
    convexities = temp_map('tmp_convexities')
    concavities = temp_map('tmp_concavities')

    r.mapcalc(
        expression='{x} = if({laplacian}>{thres}, 1, 0)'\
        .format(x=convexities, laplacian=laplacian, thres=curv_thres),
        quiet=True)
    r.mapcalc(
        expression='{x} = if({laplacian}<-{thres}, 1, 0)'\
        .format(x=concavities, laplacian=laplacian, thres=curv_thres),
        quiet=True)

    # calculate density of convexities and concavities
    gs.message("3. Using resampling filter to create surface convexity/concavity...")
    resample_convex = temp_map('tmp_convex')
    resample_concav = temp_map('tmp_concav')
    r.resamp_filter(input=convexities, output=resample_convex,
                    filter=['bartlett','gauss'], radius=[x_radius,y_radius],
                    quiet=True)
    r.resamp_filter(input=concavities, output=resample_concav,
                    filter=['bartlett','gauss'], radius=[x_radius,y_radius],
                    quiet=True)

    # convert to percentages
    gs.message("4. Converting to percentages...")
    g.region(**current_reg)
    r.mask(raster=elevation, overwrite=True, quiet=True)
    r.mapcalc(expression='{x} = float({y} * 100)'.format(x=convexity, y=resample_convex),
               quiet=True)
    r.mapcalc(expression='{x} = float({y} * 100)'.format(x=concavity, y=resample_concav),
               quiet=True)
    r.mask(flags='r', quiet=True)

    # set colors
    r.colors_stddev(map=convexity, quiet=True)
    r.colors_stddev(map=concavity, quiet=True)

    # Terrain classification Flowchart-----------------------------------------
    if features != '':
        gs.message("Performing terrain surface classification...")
        # level 1 produces classes 1 thru 8
        # level 2 produces classes 5 thru 12
        # level 3 produces classes 9 thru 16
        if nclasses == 8: levels = 1
        if nclasses == 12: levels = 2
        if nclasses == 16: levels = 3

        classif = []
        for level in range(levels):
            # mask previous classes x:x+4
            if level != 0:
                min_cla = (4*(level+1))-4
                clf_msk = temp_map('tmp_clf_mask')
                rules = '1:{0}:1'.format(min_cla)
                r.recode(
                    input=classif[level-1], output=clf_msk,
                    rules=string_to_rules(rules), overwrite=True)
                r.mask(raster=clf_msk, flags='i', quiet=True, overwrite=True)

            # image statistics
            smean = r.univar(
                map=slope, flags='g', stdout_=PIPE).outputs.stdout.split(os.linesep)
            smean = [i for i in smean if i.startswith('mean=') is True][0].split('=')[1]

            cmean = r.univar(
                map=convexity, flags='g', stdout_=PIPE).outputs.stdout.split(os.linesep)
            cmean = [i for i in cmean if i.startswith('mean=') is True][0].split('=')[1]

            tmean = r.univar(
                map=texture, flags='g', stdout_=PIPE).outputs.stdout.split(os.linesep)
            tmean = [i for i in tmean if i.startswith('mean=') is True][0].split('=')[1]
            classif.append(temp_map('tmp_classes'))
            
            if level != 0:
                r.mask(flags='r', quiet=True)

            classification(level+1, slope, smean, texture, tmean,
                            convexity, cmean, classif[level])

        # combine decision trees
        merged = []
        for level in range(0, levels):
            if level > 0:
                min_cla = (4*(level+1))-4
                merged.append(temp_map('tmp_merged'))
                r.mapcalc(
                    expression='{x} = if({a}>{min}, {b}, {a})'.format(
                        x=merged[level], min=min_cla, a=merged[level-1],  b=classif[level]))
            else:
                merged.append(classif[level])
        g.rename(raster=[merged[-1], features], quiet=True)
        del TMP_RAST[-1]

    # Write metadata ----------------------------------------------------------
    history = 'r.terrain.texture '
    for key,val in options.iteritems():
        history += key + '=' + str(val) + ' '

    r.support(map=texture,
              title=texture,
              description='generated by r.terrain.texture',
              history=history)
    r.support(map=convexity,
              title=convexity,
              description='generated by r.terrain.texture',
              history=history)
    r.support(map=concavity,
              title=concavity,
              description='generated by r.terrain.texture',
              history=history)

    if features != '':
        r.support(map=features,
                  title=features,
                  description='generated by r.terrain.texture',
                  history=history)
        
        # write color and category rules to tempfiles                
        r.category(
            map=features,
            rules=string_to_rules(categories(nclasses)),
            separator='pipe')
        r.colors(
            map=features, rules=string_to_rules(colors(nclasses)), quiet=True)

    return 0