Re: [GRASS-user] Classify basins as "narrow"

2020-09-03 Thread Ken Mankoff

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"

2020-09-03 Thread Ken Mankoff

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"

2020-09-03 Thread Ken Mankoff
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"

2020-09-03 Thread Moritz Lennert

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"

2020-09-03 Thread Stefan Blumentrath
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"

2020-09-02 Thread Ken Mankoff
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"

2020-09-02 Thread Ken Mankoff
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"

2020-09-02 Thread Markus Neteler
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"

2020-09-02 Thread Markus Neteler
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"

2020-09-02 Thread Ken Mankoff
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