Example #1
0
def derive_HAND(dem,
                ldd,
                accuThreshold,
                rivers=None,
                basin=None,
                up_area=None):
    """
    Function derives Height-Above-Nearest-Drain.
    See http://www.sciencedirect.com/science/article/pii/S003442570800120X
    Input:
        dem -- pcraster object float32, elevation data
        ldd -- pcraster object direction, local drain directions
        accuThreshold -- upstream amount of cells as threshold for river
            delineation
        rivers=None -- you can provide a rivers layer here. Pixels that are
                        identified as river should have a value > 0, other
                        pixels a value of zero.
        basin=None -- set a boolean pcraster map where areas with True are estimated using the nearest drain in ldd distance
                        and areas with False by means of the nearest friction distance. Friction distance estimated using the
                        upstream area as weight (i.e. drains with a bigger upstream area have a lower friction)
                        the spreadzone operator is used in this case.
        up_area=None -- provide the upstream area (if not assigned a guesstimate is prepared, assuming the LDD covers a
                        full catchment area)
    Output:
        hand -- pcraster bject float32, height, normalised to nearest stream
        dist -- distance to nearest stream measured in cell lengths
            according to D8 directions
    """
    if rivers is None:
        # prepare stream from a strahler threshold
        stream = pcr.ifthenelse(
            pcr.accuflux(ldd, 1) >= accuThreshold, pcr.boolean(1),
            pcr.boolean(0))
    else:
        # convert stream network to boolean
        stream = pcr.boolean(pcr.cover(rivers, 0))
    # determine height in river (in DEM*100 unit as ordinal)
    height_river = pcr.ifthenelse(stream, pcr.ordinal(dem * 100), 0)
    if basin is None:
        up_elevation = pcr.scalar(pcr.subcatchment(ldd, height_river))
    else:
        # use basin to allocate areas outside basin to the nearest stream. Nearest is weighted by upstream area
        if up_area is None:
            up_area = pcr.accuflux(ldd, 1)
        up_area = pcr.ifthen(stream, up_area)  # mask areas outside streams
        friction = 1. / pcr.scalar(
            pcr.spreadzone(pcr.cover(pcr.ordinal(up_area), 0), 0, 0))
        # if basin, use nearest river within subcatchment, if outside basin, use weighted-nearest river
        up_elevation = pcr.ifthenelse(
            basin, pcr.scalar(pcr.subcatchment(ldd, height_river)),
            pcr.scalar(pcr.spreadzone(height_river, 0, friction)))
        # replace areas outside of basin by a spread zone calculation.
    hand = pcr.max(pcr.scalar(pcr.ordinal(dem * 100)) - up_elevation,
                   0) / 100  # convert back to float in DEM units
    # hand = (pcr.scalar(pcr.ordinal(dem*100))-up_elevation)/100  # convert back to float in DEM units
    dist = pcr.ldddist(ldd, stream, 1)  # compute horizontal distance estimate
    return hand, dist
Example #2
0
def derive_HAND(dem, ldd, accuThreshold, rivers=None, basin=None, up_area=None, neg_HAND=None):
    """
    Function derives Height-Above-Nearest-Drain.
    See http://www.sciencedirect.com/science/article/pii/S003442570800120X
    Input:
        dem -- pcraster object float32, elevation data
        ldd -- pcraster object direction, local drain directions
        accuThreshold -- upstream amount of cells as threshold for river
            delineation
        rivers=None -- you can provide a rivers layer here. Pixels that are
                        identified as river should have a value > 0, other
                        pixels a value of zero.
        basin=None -- set a boolean pcraster map where areas with True are estimated using the nearest drain in ldd distance
                        and areas with False by means of the nearest friction distance. Friction distance estimated using the
                        upstream area as weight (i.e. drains with a bigger upstream area have a lower friction)
                        the spreadzone operator is used in this case.
        up_area=None -- provide the upstream area (if not assigned a guesstimate is prepared, assuming the LDD covers a
                        full catchment area)
        neg_HAND=None -- if set to 1, HAND maps can have negative values when elevation outside of stream is lower than
                        stream (for example when there are natural embankments)
    Output:
        hand -- pcraster bject float32, height, normalised to nearest stream
        dist -- distance to nearest stream measured in cell lengths
            according to D8 directions
    """
    if rivers is None:
        # prepare stream from a strahler threshold
        stream = pcr.ifthenelse(pcr.accuflux(ldd, 1) >= accuThreshold,
                                pcr.boolean(1), pcr.boolean(0))
    else:
        # convert stream network to boolean
        stream = pcr.boolean(pcr.cover(rivers, 0))
    # determine height in river (in DEM*100 unit as ordinal)
    height_river = pcr.ifthenelse(stream, pcr.ordinal(dem*100), 0)
    if basin is None:
        up_elevation = pcr.scalar(pcr.subcatchment(ldd, height_river))
    else:
        # use basin to allocate areas outside basin to the nearest stream. Nearest is weighted by upstream area
        if up_area is None:
            up_area = pcr.accuflux(ldd, 1)
        up_area = pcr.ifthen(stream, up_area)  # mask areas outside streams
        friction = 1./pcr.scalar(pcr.spreadzone(pcr.cover(pcr.ordinal(up_area), 0), 0, 0))
        # if basin, use nearest river within subcatchment, if outside basin, use weighted-nearest river
        up_elevation = pcr.ifthenelse(basin, pcr.scalar(pcr.subcatchment(ldd, height_river)), pcr.scalar(pcr.spreadzone(height_river, 0, friction)))
        # replace areas outside of basin by a spread zone calculation.
    # make negative HANDS also possible
    if neg_HAND == 1:
        hand = (pcr.scalar(pcr.ordinal(dem*100))-up_elevation)/100  # convert back to float in DEM units
    else:
        hand = pcr.max(pcr.scalar(pcr.ordinal(dem*100))-up_elevation, 0)/100  # convert back to float in DEM units
    dist = pcr.ldddist(ldd, stream, 1)  # compute horizontal distance estimate
    return hand, dist
Example #3
0
def derive_HAND(dem, ldd, accuThreshold, rivers=None, basin=None):
    """
    Function derives Height-Above-Nearest-Drain.
    See http://www.sciencedirect.com/science/article/pii/S003442570800120X
    Input:
        dem -- pcraster object float32, elevation data
        ldd -- pcraster object direction, local drain directions
        accuThreshold -- upstream amount of cells as threshold for river
            delineation
        rivers=None -- you can provide a rivers layer here. Pixels that are
                        identified as river should have a value > 0, other
                        pixels a value of zero.
        basin=None -- set a boolean pcraster map where areas with True are estimated using the nearest drain in ldd distance
                        and areas with False by means of the nearest friction distance. Friction distance estimated using the
                        upstream area as weight (i.e. drains with a bigger upstream area have a lower friction)
                        the spreadzone operator is used in this case.
    Output:
        hand -- pcraster bject float32, height, normalised to nearest stream
        dist -- distance to nearest stream measured in cell lengths
            according to D8 directions
    """
    if rivers is None:
        stream = pcr.ifthenelse(
            pcr.accuflux(ldd, 1) >= accuThreshold, pcr.boolean(1), pcr.boolean(0)
        )
    else:
        stream = pcr.boolean(pcr.cover(rivers, 0))

    height_river = pcr.ifthenelse(stream, pcr.ordinal(dem * 100), 0)
    if basin is None:
        up_elevation = pcr.scalar(pcr.subcatchment(ldd, height_river))
    else:
        drainage_surf = pcr.ifthen(rivers, pcr.accuflux(ldd, 1))
        weight = 1.0 / pcr.scalar(
            pcr.spreadzone(pcr.cover(pcr.ordinal(drainage_surf), 0), 0, 0)
        )
        up_elevation = pcr.ifthenelse(
            basin,
            pcr.scalar(pcr.subcatchment(ldd, height_river)),
            pcr.scalar(pcr.spreadzone(height_river, 0, weight)),
        )
        # replace areas outside of basin by a spread zone calculation.
    hand = pcr.max(pcr.scalar(pcr.ordinal(dem * 100)) - up_elevation, 0) / 100
    dist = pcr.ldddist(ldd, stream, 1)

    return hand, dist
Example #4
0
def derive_HAND(dem, ldd, accuThreshold, rivers=None, basin=None):
    """
    Function derives Height-Above-Nearest-Drain.
    See http://www.sciencedirect.com/science/article/pii/S003442570800120X
    Input:
        dem -- pcraster object float32, elevation data
        ldd -- pcraster object direction, local drain directions
        accuThreshold -- upstream amount of cells as threshold for river
            delineation
        rivers=None -- you can provide a rivers layer here. Pixels that are
                        identified as river should have a value > 0, other
                        pixels a value of zero.
        basin=None -- set a boolean pcraster map where areas with True are estimated using the nearest drain in ldd distance
                        and areas with False by means of the nearest friction distance. Friction distance estimated using the
                        upstream area as weight (i.e. drains with a bigger upstream area have a lower friction)
                        the spreadzone operator is used in this case.
    Output:
        hand -- pcraster bject float32, height, normalised to nearest stream
        dist -- distance to nearest stream measured in cell lengths
            according to D8 directions
    """
    if rivers is None:
        stream = pcr.ifthenelse(
            pcr.accuflux(ldd, 1) >= accuThreshold, pcr.boolean(1), pcr.boolean(0)
        )
    else:
        stream = pcr.boolean(pcr.cover(rivers, 0))

    height_river = pcr.ifthenelse(stream, pcr.ordinal(dem * 100), 0)
    if basin is None:
        up_elevation = pcr.scalar(pcr.subcatchment(ldd, height_river))
    else:
        drainage_surf = pcr.ifthen(rivers, pcr.accuflux(ldd, 1))
        weight = 1.0 / pcr.scalar(
            pcr.spreadzone(pcr.cover(pcr.ordinal(drainage_surf), 0), 0, 0)
        )
        up_elevation = pcr.ifthenelse(
            basin,
            pcr.scalar(pcr.subcatchment(ldd, height_river)),
            pcr.scalar(pcr.spreadzone(height_river, 0, weight)),
        )
        # replace areas outside of basin by a spread zone calculation.
    hand = pcr.max(pcr.scalar(pcr.ordinal(dem * 100)) - up_elevation, 0) / 100
    dist = pcr.ldddist(ldd, stream, 1)

    return hand, dist
def generate_hydro_datasets(path, output_dir, step):
    print(path)

    file_name = os.path.splitext(os.path.basename(path))[0]
    map_path = output_dir + '/' + file_name + '.map'
    path_prefix = map_path[:-14]

    if step == 'ldd':
        cmd = u'gdal_translate -a_nodata -9999 -of PCRaster -ot Float32 ' + path + ' ' + map_path
        print(cmd)
        subprocess.call(cmd, shell=True)

    # slope = pcr.slope(dem)
    # pcr.report(slope, path_prefix + '_slope.map')

    # pcr.setglobaloption("lddin")

    if step == 'ldd':
        dem = pcr.readmap(map_path)

        print("Computing LDD ...")
        # enable pit filling
        ldd = pcr.lddcreate(dem, 9999999, 9999999, 9999999, 9999999)
        pcr.report(ldd, path_prefix + '_ldd.map')

        return
    elif step == 'ldddem':
        dem = pcr.readmap(map_path)

        print("Computing LDD DEM ...")
        dem_pitfilled = pcr.lddcreatedem(dem, 9999999, 9999999, 9999999,
                                         9999999)
        dem_diff = dem_pitfilled - dem
        pcr.report(dem_diff, path_prefix + '_dem_pits_diff.map')

        return

    # print("Computing LDD without pit filling ...")
    # ldd_pits = pcr.lddcreate(dem, 0, 0, 0, 0)
    # pcr.report(ldd_pits, path_prefix + '_ldd_with_pits.map')

    # print("Computing pits ...")
    # pits = pcr.pit(ldd_pits)

    # pcr.report(pits, path_prefix + '_pits.map')

    if step == 'fa':
        ldd = pcr.readmap(path_prefix + '_ldd.map')

        print("Computing flow accumulation ...")
        fa = pcr.accuflux(ldd, 1)
        pcr.report(fa, path_prefix + '_fa.map')

        return

    if step == 'catchments':
        ldd = pcr.readmap(path_prefix + '_ldd.map')

        print("Delineating catchments ...")
        catchments = pcr.catchment(ldd, pcr.pit(ldd))
        pcr.report(catchments, path_prefix + '_catchments.map')

        return

    if step == 'stream_order':
        ldd = pcr.readmap(path_prefix + '_ldd.map')

        print("Computing stream order ...")
        stream_order = pcr.streamorder(ldd)
        pcr.report(stream_order, path_prefix + '_streamorder.map')

        return

    if step == 'stream':
        ldd = pcr.readmap(path_prefix + '_ldd.map')
        accuThreshold = 100
        print("Computing stream ...")
        stream = pcr.ifthenelse(
            pcr.accuflux(ldd, 1) >= accuThreshold, pcr.boolean(1),
            pcr.boolean(0))
        pcr.report(stream, path_prefix + '_stream.map')
        return

    if step == 'height_river':
        print("Computing heigh_river ...")

        stream = pcr.readmap(path_prefix + '_stream.map')
        dem = pcr.readmap(map_path)
        height_river = pcr.ifthenelse(stream, pcr.ordinal(dem), 0)
        pcr.report(height_river, path_prefix + '_height_river.map')
        return

    if step == 'up_elevation':
        print("Computing up_elevation ...")

        height_river = pcr.readmap(path_prefix + '_height_river.map')
        ldd = pcr.readmap(path_prefix + '_ldd.map')
        up_elevation = pcr.scalar(pcr.subcatchment(ldd, height_river))
        pcr.report(up_elevation, path_prefix + '_up_elevation.map')
        return

    if step == 'hand':
        print("Computing HAND ...")
        dem = pcr.readmap(map_path)
        up_elevation = pcr.readmap(path_prefix + '_up_elevation.map')
        hand = pcr.max(dem - up_elevation, 0)
        pcr.report(hand, path_prefix + '_hand.map')
        return

    if step == 'dand':
        print("Computing DAND ...")
        ldd = pcr.readmap(path_prefix + '_ldd.map')
        stream = pcr.readmap(path_prefix + '_stream.map')
        dist = pcr.ldddist(ldd, stream, 1)
        pcr.report(dist, path_prefix + '_dist.map')
        return

    if step == 'fa_river':
        print("Computing FA river ...")
        fa = pcr.readmap(path_prefix + '_fa.map')
        stream = pcr.readmap(path_prefix + '_stream.map')
        fa_river = pcr.ifthenelse(stream, pcr.ordinal(fa), 0)
        pcr.report(fa_river, path_prefix + '_fa_river.map')
        return

    if step == 'faand':
        print("Computing FAAND ...")
        fa_river = pcr.readmap(path_prefix + '_fa_river.map')
        ldd = pcr.readmap(path_prefix + '_ldd.map')
        up_fa = pcr.scalar(pcr.subcatchment(ldd, fa_river))
        pcr.report(up_fa, path_prefix + '_faand.map')
        return
Example #6
0
def pcr_inun(dem, ids, h_bounds, ids_coastline,
                resistance=0.,  water_perc=None, zero_resistance_waterp=1.0,
                cellres=1, dist_method='eucledian', ldd=None):
    """ planar inundation routine per segment

    :param dem:             pcr dem
    :param ids:             local ids of boundary conditions, starting a 1 (not zero!)
    :param h_bounds:        water level boundary at diva segment
    :param ids_coastline:   pcraster map with coastal segments ids
    :param resistance:      constant or pcrmap unit km-1; (default 0: no resistance is calculated)
    :param cellres:         cell resolution in km, varies with latitude degrees
    :param ldd:             pcraster map with local drainage direction to calculate resistance along ldd;
                            if None (default) resistance is calculated using 'plain' nearest neighbour


    :return:                pcrmap with flood depth
    """
    pcr.setglobaloption("unitcell")
    if resistance > 0:
        coastline = pcr.cover(pcr.ifthenelse(pcr.scalar(ids_coastline) > 0, pcr.boolean(1), 0), pcr.boolean(0))
        mask = pcr.ifthen(dem > -9999, pcr.scalar(1))
        if dist_method == 'ldd':
            # Distance to coast along ldd
            dist2coast0 = pcr.ldddist(ldd, coastline, cellres)
            # find edge of area with distances -> water divide
            dist2coast_mask = pcr.cover(pcr.ifthenelse(dist2coast0 > 0, pcr.boolean(0), pcr.boolean(1)),
                                        pcr.boolean(1))
            start = pcr.ifthenelse(
                ((pcr.window4total(pcr.scalar(dist2coast_mask)) > 0) & (dist2coast_mask == pcr.boolean(0))) |
                coastline,
                pcr.boolean(1), pcr.boolean(0))
            # continue distance beyond water divide with eucledian dist
            dist2coast1 = pcr.spread(start, dist2coast0, cellres*mask)
            dist2coast = pcr.ifthenelse(dist2coast_mask, dist2coast1, dist2coast0)

        elif dist_method == 'eucledian':
            # dist to coast using nearest neighbor
            if water_perc is None:
                dist2coast = pcr.spread(coastline, 0, cellres*mask)
            else:
                # zero resistance for cells with water_perc >= zero_resistance_waterp
                zrw = float(zero_resistance_waterp)
                water_perc = pcr.ifthenelse(water_perc >= zrw,
                                            pcr.scalar(1),
                                            water_perc / zrw)
                dist2coast = pcr.spread(coastline, 0, cellres*mask*(1 - water_perc))

        dem_adjust = dem + pcr.cover(dist2coast, 0) * pcr.scalar(resistance)   # raise the elevation using a damping factor
    else:
        dem_adjust = dem
        dist2coast = pcr.scalar(1)

    fld_depth = pcr.ifthen(dem > -9999, pcr.scalar(0))

    for i, h in zip(ids, h_bounds):
        coast_segment = pcr.ifthenelse(ids_coastline == i, pcr.boolean(1), pcr.boolean(0))

        # find area below flood_level
        fld_prone = pcr.ifthenelse(dem_adjust <= pcr.scalar(float(h)), pcr.boolean(1), pcr.boolean(0))
        # make contiguous groups of cells which are below flood level
        fld_clump = pcr.clump(fld_prone)
        # find flooded area connected to diva segment
        fld_coast = pcr.ifthenelse(pcr.areamaximum(pcr.scalar(fld_clump) * pcr.scalar(coast_segment), fld_clump) > 0,
                                   pcr.boolean(1), pcr.boolean(0))
        # get max fld depth map
        fld_depth = pcr.max(fld_depth, pcr.ifthenelse(fld_coast, pcr.scalar(pcr.scalar(float(h)) - dem_adjust), 0))

    return fld_depth, dist2coast, dem_adjust
def generate_hydro_datasets(path, output_dir, step):
    print(path)

    file_name = os.path.splitext(os.path.basename(path))[0]
    map_path = output_dir + "/" + file_name + ".map"
    path_prefix = map_path[:-14]

    if step == "ldd":
        cmd = u"gdal_translate -a_nodata -9999 -of PCRaster -ot Float32 " + path + " " + map_path
        print(cmd)
        subprocess.call(cmd, shell=True)

    # slope = pcr.slope(dem)
    # pcr.report(slope, path_prefix + '_slope.map')

    # pcr.setglobaloption("lddin")

    if step == "ldd":
        dem = pcr.readmap(map_path)

        print("Computing LDD ...")
        # enable pit filling
        ldd = pcr.lddcreate(dem, 9999999, 9999999, 9999999, 9999999)
        pcr.report(ldd, path_prefix + "_ldd.map")

        return
    elif step == "ldddem":
        dem = pcr.readmap(map_path)

        print("Computing LDD DEM ...")
        dem_pitfilled = pcr.lddcreatedem(dem, 9999999, 9999999, 9999999, 9999999)
        dem_diff = dem_pitfilled - dem
        pcr.report(dem_diff, path_prefix + "_dem_pits_diff.map")

        return

    # print("Computing LDD without pit filling ...")
    # ldd_pits = pcr.lddcreate(dem, 0, 0, 0, 0)
    # pcr.report(ldd_pits, path_prefix + '_ldd_with_pits.map')

    # print("Computing pits ...")
    # pits = pcr.pit(ldd_pits)

    # pcr.report(pits, path_prefix + '_pits.map')

    if step == "fa":
        ldd = pcr.readmap(path_prefix + "_ldd.map")

        print("Computing flow accumulation ...")
        fa = pcr.accuflux(ldd, 1)
        pcr.report(fa, path_prefix + "_fa.map")

        return

    if step == "catchments":
        ldd = pcr.readmap(path_prefix + "_ldd.map")

        print("Delineating catchments ...")
        catchments = pcr.catchment(ldd, pcr.pit(ldd))
        pcr.report(catchments, path_prefix + "_catchments.map")

        return

    if step == "stream_order":
        ldd = pcr.readmap(path_prefix + "_ldd.map")

        print("Computing stream order ...")
        stream_order = pcr.streamorder(ldd)
        pcr.report(stream_order, path_prefix + "_streamorder.map")

        return

    if step == "stream":
        ldd = pcr.readmap(path_prefix + "_ldd.map")
        accuThreshold = 100
        print("Computing stream ...")
        stream = pcr.ifthenelse(pcr.accuflux(ldd, 1) >= accuThreshold, pcr.boolean(1), pcr.boolean(0))
        pcr.report(stream, path_prefix + "_stream.map")
        return

    if step == "height_river":
        print("Computing heigh_river ...")

        stream = pcr.readmap(path_prefix + "_stream.map")
        dem = pcr.readmap(map_path)
        height_river = pcr.ifthenelse(stream, pcr.ordinal(dem), 0)
        pcr.report(height_river, path_prefix + "_height_river.map")
        return

    if step == "up_elevation":
        print("Computing up_elevation ...")

        height_river = pcr.readmap(path_prefix + "_height_river.map")
        ldd = pcr.readmap(path_prefix + "_ldd.map")
        up_elevation = pcr.scalar(pcr.subcatchment(ldd, height_river))
        pcr.report(up_elevation, path_prefix + "_up_elevation.map")
        return

    if step == "hand":
        print("Computing HAND ...")
        dem = pcr.readmap(map_path)
        up_elevation = pcr.readmap(path_prefix + "_up_elevation.map")
        hand = pcr.max(dem - up_elevation, 0)
        pcr.report(hand, path_prefix + "_hand.map")
        return

    if step == "dand":
        print("Computing DAND ...")
        ldd = pcr.readmap(path_prefix + "_ldd.map")
        stream = pcr.readmap(path_prefix + "_stream.map")
        dist = pcr.ldddist(ldd, stream, 1)
        pcr.report(dist, path_prefix + "_dist.map")
        return

    if step == "fa_river":
        print("Computing FA river ...")
        fa = pcr.readmap(path_prefix + "_fa.map")
        stream = pcr.readmap(path_prefix + "_stream.map")
        fa_river = pcr.ifthenelse(stream, pcr.ordinal(fa), 0)
        pcr.report(fa_river, path_prefix + "_fa_river.map")
        return

    if step == "faand":
        print("Computing FAAND ...")
        fa_river = pcr.readmap(path_prefix + "_fa_river.map")
        ldd = pcr.readmap(path_prefix + "_ldd.map")
        up_fa = pcr.scalar(pcr.subcatchment(ldd, fa_river))
        pcr.report(up_fa, path_prefix + "_faand.map")
        return