Re: [GRASS-user] Classify basins as "narrow"
On 2020-09-03 at 09:27 -07, Ken Mankoff wrote... > I have skeletons: > > r.to.vect -v input=basins output=basins type=area > v.to.lines input=basins output=bounds Sorry - that's exoskeleton (boundary), not skeleton. The Voronoi skeleton is a powerful tool to simplify the algorithm. Thanks again for this suggestion. > But the voronoi centerline, and then dist from center line to edges, > is a much tighter algorithm than the current one (distance from edges > -> invert -> stream route -> extract stream as centerline -> dist from > center to edges). -k. ___ grass-user mailing list grass-user@lists.osgeo.org https://lists.osgeo.org/mailman/listinfo/grass-user
Re: [GRASS-user] Classify basins as "narrow"
On 2020-09-02 at 23:59 -07, Moritz Lennert wrote... > There is also v.voronoi with the -s flag for extraction of skeletons > from vector polygons. I have skeletons: r.to.vect -v input=basins output=basins type=area v.to.lines input=basins output=bounds But the voronoi centerline, and then dist from center line to edges, is a much tighter algorithm than the current one (distance from edges -> invert -> stream route -> extract stream as centerline -> dist from center to edges). Thank you! -k. ___ grass-user mailing list grass-user@lists.osgeo.org https://lists.osgeo.org/mailman/listinfo/grass-user
Re: [GRASS-user] Classify basins as "narrow"
Hi Stefan, Thank you for these suggestions. I think I need to stick with my more complex workflow for the following reason: Narrowness needs to be computed from the centerline to the edge, rather than from the edge to the center, so that the case of a narrow basin next to a wide basin is properly handled. If you compute from the edge, then the edge of the wide basin would also be considered narrow. Other advantages of the more complex workflow is that the "r.neighbors maximum" suggestion appears to be a binary classifier, while with the more complex method values are actual basin widths, which is better for the downstream fuzzy logic application than a crisp value. Finally, reviewing my code it looks like the "must do this for each basin individually" part at the bottom is incorrect, and the code can be run 1x for all basins. Thank you again for the suggestions, -k. On 2020-09-02 at 23:54 -07, Stefan Blumentrath wrote... > Hei Ken, > > What about a combination of r.grow.distance and r.neighbors? > > 1) Extract boundaries from raster basins > r.neighbors input=basins output=basin_diversity method=diversity > r.reclass input=basin_diversity output=basin_boundary rc=- > "1 = NULL > 2 thru 999 = 1" (if you need the boundaries later on the vector solution > is probably more efficient) > > 2) compute distance from boundaries > r.grow.distance input=basin_boundary output=basin_boundary_distance > > 3) get the maximum distance from the boundaries > r.neighbors method=maximum size="twice what you would consider narrow" > > Depends if it is computationally more efficient... If narrow still > means "a lot" of pixels in width, then r.neighbors might be relatively > slow. But you might increase resolution in that case. > > In order to get the skeleton of the basin you could use r.neighbors as > well: r.neighbors input=basin_boundary_distance method=maximum > output=basin_boundary_distance_max r.mapcalc > expression="skeletons=if(basin_boundary_distance < > basin_boundary_distance_max, null(), 1)" This should approximate the > center lines... Note that you could skip r.neighbors and use the > neighborhood modifier in r.mapcalc... > > Just some ideas for the width issue... > > Cheers, > Stefan ___ grass-user mailing list grass-user@lists.osgeo.org https://lists.osgeo.org/mailman/listinfo/grass-user
Re: [GRASS-user] Classify basins as "narrow"
On 3/09/20 08:54, Stefan Blumentrath wrote: In order to get the skeleton of the basin you could use r.neighbors as well: r.neighbors input=basin_boundary_distance method=maximum output=basin_boundary_distance_max r.mapcalc expression="skeletons=if(basin_boundary_distance < basin_boundary_distance_max, null(), 1)" This should approximate the center lines... There is also v.voronoi with the -s flag for extraction of skeletons from vector polygons. Moritz ___ grass-user mailing list grass-user@lists.osgeo.org https://lists.osgeo.org/mailman/listinfo/grass-user
Re: [GRASS-user] Classify basins as "narrow"
Hei Ken, What about a combination of r.grow.distance and r.neighbors? 1) Extract boundaries from raster basins r.neighbors input=basins output=basin_diversity method=diversity r.reclass input=basin_diversity output=basin_boundary rc=- "1 = NULL 2 thru 999 = 1" (if you need the boundaries later on the vector solution is probably more efficient) 2) compute distance from boundaries r.grow.distance input=basin_boundary output=basin_boundary_distance 3) get the maximum distance from the boundaries r.neighbors method=maximum size="twice what you would consider narrow" Depends if it is computationally more efficient... If narrow still means "a lot" of pixels in width, then r.neighbors might be relatively slow. But you might increase resolution in that case. In order to get the skeleton of the basin you could use r.neighbors as well: r.neighbors input=basin_boundary_distance method=maximum output=basin_boundary_distance_max r.mapcalc expression="skeletons=if(basin_boundary_distance < basin_boundary_distance_max, null(), 1)" This should approximate the center lines... Note that you could skip r.neighbors and use the neighborhood modifier in r.mapcalc... Just some ideas for the width issue... Cheers, Stefan -Original Message- From: grass-user On Behalf Of Ken Mankoff Sent: onsdag 2. september 2020 20:03 To: GRASS user list Subject: Re: [GRASS-user] Classify basins as "narrow" Hi List, On 2020-09-02 at 04:27 -07, Ken Mankoff wrote... > I'd like to detect "narrow" features in GRASS. The attached screenshot > shows some basins (thick) and streams (thin) and some regions > (hatched). These regions are spurious because the basin is narrow > here. I'd like to estimate narrowness with an algorithm. > > I've looked into r.grow.distance r.distance and v.distance but haven't > been able to imagine a solution yet. Can anyone on this list suggest > something? I've solved this, although it takes a lot of steps, and it only computes the width of the downstream region, not everywhere. The downstream/outflow region is what I'm interested in (but didn't specify this in my initial post) so this is OK with me. By this I mean that for a "Y" shaped catchment with three narrow regions and outflow at the bottom of the stem, the current algorithm will compute the width of one of the branches and the stem, but not the other branch. I'm sharing this in case it helps someone else, or someone sees a way to do this more efficiently (perhaps all basins at once?). Here is the algorithm: # elevation raster is input # compute streams, outlets, and basins r.stream.extract elevation=elevation threshold=11 memory=16384 direction=dir stream_raster=streams stream_vector=streams r.mapcalc "outlets = if(dir < 0, 1, null())" # outlets r.to.vect input=outlets output=outlets type=point r.stream.basins -m direction=dir points=outlets basins=basins memory=16384 # basins # compute distance from edge of each basin r.to.vect -v input=basins output=basins type=area v.to.lines input=basins output=bounds v.to.rast -d input=bounds output=bounds use=val val=1 r.grow.distance input=bounds distance=edge_dist metric=euclidean # Now the algorithm can only work on one basin at a time. # Pick a basin with narrow outlet region manually, and mask to that basin. basin_id=1174 r.mask raster=basins maskcats=${basin_id} --o # Invert so center line is low, but make outlet lowest. # Edge dist is 0 at edges, so this cost surface is a hole # Make the outlet the lowest point so it pours from there. r.mapcalc "cost_surf = if(isnull(outlets), -edge_dist, -max(edge_dist)-100)" # Route a stream down the center line r.stream.extract elevation=cost_surf threshold=11 memory=16384 direction=cost_dir stream_raster=cost_streams stream_vector=cost_streams # Find the main stream (hack = 1) r.stream.order -m stream_rast=cost_streams direction=cost_dir elevation=cost_surf hack=hack memory=16384 r.mapcalc "hack_1 = if(hack == 1, 1, null())" # Grow center stream to edges r.grow.distance -m input=hack_1 distance=center_dist # DONE Now the value of center_dist at the basin boundary is the distance to the center line, or 1/2 the width. ___ grass-user mailing list grass-user@lists.osgeo.org https://lists.osgeo.org/mailman/listinfo/grass-user ___ grass-user mailing list grass-user@lists.osgeo.org https://lists.osgeo.org/mailman/listinfo/grass-user
Re: [GRASS-user] Classify basins as "narrow"
Hi Markus, On 2020-09-02 at 09:28 -07, Markus Neteler wrote... > On Wed, Sep 2, 2020 at 1:27 PM Ken Mankoff wrote: >> I'd like to detect "narrow" features in GRASS. The attached >> screenshot shows some basins (thick) and streams (thin) and some >> regions (hatched). These regions are spurious because the basin is >> narrow here. I'd like to estimate narrowness with an algorithm. > > Perhaps the compact measure of > > https://grass.osgeo.org/grass78/manuals/v.to.db.html --> compact: > compactness of an area, calculated as compactness = perimeter / (2 * > sqrt(PI * area)) > > could help here? Thank you for sharing this. I did not see your email when I wrote my reply with my solution. I need spatial variance in the result, not a single measure per-basin (that is, I want to be able to say "look out for results in this part of the basin, it is narrow, but don't worry elsewhere in this basin"). However, elsewhere on this project I need to know something about neighboring basins, and was looking into that. Your suggestion to read the v.to.db page led me to the "sides" option there, which I think solves that issue. Thank you! -k. ___ grass-user mailing list grass-user@lists.osgeo.org https://lists.osgeo.org/mailman/listinfo/grass-user
Re: [GRASS-user] Classify basins as "narrow"
Hi List, On 2020-09-02 at 04:27 -07, Ken Mankoff wrote... > I'd like to detect "narrow" features in GRASS. The attached screenshot > shows some basins (thick) and streams (thin) and some regions > (hatched). These regions are spurious because the basin is narrow > here. I'd like to estimate narrowness with an algorithm. > > I've looked into r.grow.distance r.distance and v.distance but haven't > been able to imagine a solution yet. Can anyone on this list suggest > something? I've solved this, although it takes a lot of steps, and it only computes the width of the downstream region, not everywhere. The downstream/outflow region is what I'm interested in (but didn't specify this in my initial post) so this is OK with me. By this I mean that for a "Y" shaped catchment with three narrow regions and outflow at the bottom of the stem, the current algorithm will compute the width of one of the branches and the stem, but not the other branch. I'm sharing this in case it helps someone else, or someone sees a way to do this more efficiently (perhaps all basins at once?). Here is the algorithm: # elevation raster is input # compute streams, outlets, and basins r.stream.extract elevation=elevation threshold=11 memory=16384 direction=dir stream_raster=streams stream_vector=streams r.mapcalc "outlets = if(dir < 0, 1, null())" # outlets r.to.vect input=outlets output=outlets type=point r.stream.basins -m direction=dir points=outlets basins=basins memory=16384 # basins # compute distance from edge of each basin r.to.vect -v input=basins output=basins type=area v.to.lines input=basins output=bounds v.to.rast -d input=bounds output=bounds use=val val=1 r.grow.distance input=bounds distance=edge_dist metric=euclidean # Now the algorithm can only work on one basin at a time. # Pick a basin with narrow outlet region manually, and mask to that basin. basin_id=1174 r.mask raster=basins maskcats=${basin_id} --o # Invert so center line is low, but make outlet lowest. # Edge dist is 0 at edges, so this cost surface is a hole # Make the outlet the lowest point so it pours from there. r.mapcalc "cost_surf = if(isnull(outlets), -edge_dist, -max(edge_dist)-100)" # Route a stream down the center line r.stream.extract elevation=cost_surf threshold=11 memory=16384 direction=cost_dir stream_raster=cost_streams stream_vector=cost_streams # Find the main stream (hack = 1) r.stream.order -m stream_rast=cost_streams direction=cost_dir elevation=cost_surf hack=hack memory=16384 r.mapcalc "hack_1 = if(hack == 1, 1, null())" # Grow center stream to edges r.grow.distance -m input=hack_1 distance=center_dist # DONE Now the value of center_dist at the basin boundary is the distance to the center line, or 1/2 the width. ___ grass-user mailing list grass-user@lists.osgeo.org https://lists.osgeo.org/mailman/listinfo/grass-user
Re: [GRASS-user] Classify basins as "narrow"
Forgot to mention: On Wed, Sep 2, 2020 at 6:28 PM Markus Neteler wrote: > On Wed, Sep 2, 2020 at 1:27 PM Ken Mankoff wrote: > > > > Hi GRASS list, > > > > I'd like to detect "narrow" features in GRASS. The attached screenshot > > shows some basins (thick) and streams (thin) and some regions (hatched). > > These regions are spurious because the basin is narrow here. I'd like to > > estimate narrowness with an algorithm. > > > > I've looked into r.grow.distance r.distance and v.distance but haven't been > > able to imagine a solution yet. Can anyone on this list suggest something? > > Perhaps the compact measure of > > https://grass.osgeo.org/grass78/manuals/v.to.db.html > --> compact: compactness of an area, calculated as compactness = > perimeter / (2 * sqrt(PI * area)) > > could help here? Related to compactness I found https://www.azavea.com/blog/2016/07/11/measuring-district-compactness-postgis/ and roughly digitized the shapes presented therein and moved them into "North Carolina" sample data area with r.region. The results of v.to.db/compactness are completely different, likely because it is a different measure from the Polsby-Popper measure used there. However, maybe a dataset to play with... Best Markus -- Markus Neteler, PhD https://www.mundialis.de - free data with free software https://grass.osgeo.org https://courses.neteler.org/blog shapes_for_compactness_NC.gpkg Description: Binary data ___ grass-user mailing list grass-user@lists.osgeo.org https://lists.osgeo.org/mailman/listinfo/grass-user
Re: [GRASS-user] Classify basins as "narrow"
On Wed, Sep 2, 2020 at 1:27 PM Ken Mankoff wrote: > > Hi GRASS list, > > I'd like to detect "narrow" features in GRASS. The attached screenshot shows > some basins (thick) and streams (thin) and some regions (hatched). These > regions are spurious because the basin is narrow here. I'd like to estimate > narrowness with an algorithm. > > I've looked into r.grow.distance r.distance and v.distance but haven't been > able to imagine a solution yet. Can anyone on this list suggest something? Perhaps the compact measure of https://grass.osgeo.org/grass78/manuals/v.to.db.html --> compact: compactness of an area, calculated as compactness = perimeter / (2 * sqrt(PI * area)) could help here? Best Markus ___ grass-user mailing list grass-user@lists.osgeo.org https://lists.osgeo.org/mailman/listinfo/grass-user
[GRASS-user] Classify basins as "narrow"
Hi GRASS list, I'd like to detect "narrow" features in GRASS. The attached screenshot shows some basins (thick) and streams (thin) and some regions (hatched). These regions are spurious because the basin is narrow here. I'd like to estimate narrowness with an algorithm. I've looked into r.grow.distance r.distance and v.distance but haven't been able to imagine a solution yet. Can anyone on this list suggest something? Thanks, -k. ___ grass-user mailing list grass-user@lists.osgeo.org https://lists.osgeo.org/mailman/listinfo/grass-user