[GRASS-dev] [GRASS GIS] #2382: d.legend: integer map legends should not be flipped upside-down

#2382: d.legend: integer map legends should not be flipped upside-down
-------------------------+--------------------------------------------------
Reporter: neteler | Owner: grass-dev@…
     Type: defect | Status: new
Priority: normal | Milestone: 7.0.0
Component: Display | Version: svn-releasebranch70
Keywords: d.legend | Platform: All
      Cpu: Unspecified |
-------------------------+--------------------------------------------------
Legend of integer (CELL) maps are shown upside-down with the
lowest value on top. This enforces the user to always activate
the -f flag:

{{{
# NC location
g.region rast=basin_50K
d.mon wx0
d.rast basin_50K
d.legend basin_50K

# other example

d.legend basin_50K
r.mapcalc "elev_int = round(elevation)"
r.colors elev_int color=srtm
d.erase
d.rast elev_int
d.legend elev_int -s
## --> upside-down, see screenshot
}}}

Expected: the legend should be with the lowest value down and the
highest up as it is for floating point maps.

Maybe trivial to fix but I am not sure where to add a "flipit" in the
main.c

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2382&gt;
GRASS GIS <http://grass.osgeo.org>

#2382: d.legend: integer map legends should not be flipped upside-down
-------------------------+--------------------------------------------------
Reporter: neteler | Owner: grass-dev@…
     Type: defect | Status: new
Priority: normal | Milestone: 7.0.0
Component: Display | Version: svn-releasebranch70
Keywords: d.legend | Platform: All
      Cpu: Unspecified |
-------------------------+--------------------------------------------------
Changes (by hamish):

* cc: grass-dev@… (added)

Comment:

It is like that for CELL maps on purpose and working as designed; it's
favouring categorical CELL maps over continuous value CELL maps.

In the NC08 dataset consider: `d.legend towns`
  (see attached screenshot)

I think we can all agree that counting from category 1 (smallest value) at
the top is how we would like that to be.

However, if there are more categories in the map than will fit on the
display frame d.legend automatically switches to a smoothed gradient
legend to avoid the user having to use the thin=, lines=, range=, or use=
options to cut down the number of boxes it tries to draw.

So it comes down to the question of is the data categorical (in which case
smallest value is at the top) or continuous gradient which happens to be
stored as integers (in which case smallest values is at the bottom). Since
CELL maps can be used for both there is no single correct answer to that,
and so the module goes with the logic that if the range of available cats
or the frame size happens to change by a little bit, pushing it over the
threshold, it will change the boxes into thin lines, but the overall view
will remain the same, it has just gone into "compressed mode".

note I built in two handy tricks to get the flip to happen without the -f
flag: in GRASS 6 (and with at= in G7) when drawing the box with the mouse
draw from bottom up instead of top down, and another way is to reverse the
order of values in the range= option.

regards,
Hamish

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2382#comment:1&gt;
GRASS GIS <http://grass.osgeo.org>

#2382: d.legend: integer map legends should not be flipped upside-down
-------------------------+--------------------------------------------------
Reporter: neteler | Owner: hamish
     Type: defect | Status: assigned
Priority: normal | Milestone: 7.0.0
Component: Display | Version: svn-releasebranch70
Keywords: d.legend | Platform: All
      Cpu: Unspecified |
-------------------------+--------------------------------------------------
Changes (by hamish):

  * owner: grass-dev@… => hamish
  * status: new => assigned

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2382#comment:2&gt;
GRASS GIS <http://grass.osgeo.org>

#2382: d.legend: integer map legends should not be flipped upside-down
-------------------------+--------------------------------------------------
Reporter: neteler | Owner: hamish
     Type: defect | Status: assigned
Priority: normal | Milestone: 7.0.0
Component: Display | Version: svn-releasebranch70
Keywords: d.legend | Platform: All
      Cpu: Unspecified |
-------------------------+--------------------------------------------------

Comment(by cmbarton):

With a background in archaeology and earth sciences, I normally expect the
smaller (i.e., older or lower) value to be at the bottom. But Hamish makes
a good case for why others would want it at the top for categorical maps.
The -f flag is not much of a pain. So I'm not sure it is worth changing a
very long-standing default. I suppose it could break a few scripts to do
so (but probably not many).

Michael

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2382#comment:3&gt;
GRASS GIS <http://grass.osgeo.org>

#2382: d.legend: integer map legends should not be flipped upside-down
-------------------------+--------------------------------------------------
Reporter: neteler | Owner: hamish
     Type: defect | Status: assigned
Priority: normal | Milestone: 7.0.0
Component: Display | Version: svn-releasebranch70
Keywords: d.legend | Platform: All
      Cpu: Unspecified |
-------------------------+--------------------------------------------------

Comment(by annakrat):

Replying to [comment:1 hamish]:

> So it comes down to the question of is the data categorical (in which
case smallest value is at the top) or continuous gradient which happens to
be stored as integers (in which case smallest values is at the bottom).
Since CELL maps can be used for both there is no single correct answer to
that, and so the module goes with the logic that if the range of available
cats or the frame size happens to change by a little bit, pushing it over
the threshold, it will change the boxes into thin lines, but the overall
view will remain the same, it has just gone into "compressed mode".
>

In my view, the order should be defined by the gradient/box legend, not by
the type of the map since it is not reliable. Gradient would have low
values in the bottom, and boxes would be ordered in the opposite
direction. This behavior could create less confusion and would be expected
in most cases, in my opinion.

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2382#comment:4&gt;
GRASS GIS <http://grass.osgeo.org>

#2382: d.legend: integer map legends should not be flipped upside-down
-------------------------+--------------------------------------------------
Reporter: neteler | Owner: hamish
     Type: defect | Status: assigned
Priority: normal | Milestone: 7.0.0
Component: Display | Version: svn-releasebranch70
Keywords: d.legend | Platform: All
      Cpu: Unspecified |
-------------------------+--------------------------------------------------

Comment(by wenzeslaus):

Replying to [comment:1 hamish]:
>
> In the NC08 dataset consider: `d.legend towns`
> (see attached screenshot)
>
> I think we can all agree that counting from category 1 (smallest value)
at the top is how we would like that to be.
>
Sorry, I cannot agree entirely. I don't see the reason to have numbers
there when labels are the only important thing in case of of towns. Then
of course the order (order according category) is not important. Although
I agree that we might suppose some ordering imprinted in categories, e.g.
in case of labels for slope.

> note I built in two handy tricks to get the flip to happen without the
-f flag: in GRASS 6 (and with at= in G7) when drawing the box with the
mouse draw from bottom up instead of top down, and another way is to
reverse the order of values in the range= option.
>
I generally agree with introducing these tricks (clever decision making,
heuristics). However, in this case it is questionable if it creates more
confusion then convenient/handy behavior. Perhaps option
`order=ascending`, `order=descending` and `order=auto` would improve the
situation by making things explicit. `order=auto` can be the default.
`order=ascending` and `order=descending` would disable any handy tricks.

--
Ticket URL: <http://trac.osgeo.org/grass/ticket/2382#comment:5&gt;
GRASS GIS <http://grass.osgeo.org>

#2382: d.legend: integer map legends should not be flipped upside-down
----------------------+-----------------------------------------------------
  Reporter: neteler | Owner: hamish
      Type: defect | Status: closed
  Priority: normal | Milestone: 7.0.0
Component: Display | Version: svn-releasebranch70
Resolution: wontfix | Keywords: d.legend
  Platform: All | Cpu: Unspecified
----------------------+-----------------------------------------------------
Changes (by hamish):

  * status: assigned => closed
  * resolution: => wontfix

Comment:

annakrat wrote:
> In my view, the order should be defined by the gradient/box legend, not
by
> the type of the map since it is not reliable. Gradient would have low
values
> in the bottom, and boxes would be ordered in the opposite direction.
This
> behavior could create less confusion and would be expected in most
cases,
> in my opinion.

"smoothed" legend != "gradient" legend

One is a visual change, the other a conceptual change. Visual adjustments
are easier to follow than conceptual ones. As the determining factor here
in rendering style is the height of the display frame -- a visual change
as well -- that's the smallest logical jump to make. A good demo of this
is if you have a map with the number of categories near to the maximum
number of boxes that will fit in the display frame, and tweak the size of
the window a bit taller and shorter to watch it jump back and forth
between rendering styles. For categorical maps it is not a gradient at
all, just a stack of blocks, often with random color transitions.

Again, there is no one right answer here for all use cases, and no way for
the software to know ahead of time. So we pick one way and hope it is the
right choice 51% of the time. Another way to make the choice is by how far
from the too-many-boxes threshold you are. That might make it do the right
thing more often for an integer elevation map with a range of 100s or
1000s of meters (admittedly a common alternative and the one which
inspired this ticket), but IMO the logic and arbitrary choice of threshold
value becomes too muddy to explain and it moves into the horrible realm of
software "auto correct"s.

wenzeslaus wrote:
> Sorry, I cannot agree entirely. I don't see the reason to have numbers
there
> when labels are the only important thing in case of of towns. Then of
course
> the order (order according category) is not important.

The towns map was just an example of a purely categorical, as opposed to
continuous gradient, CELL map with a useful number of categories. Of
course the category numbers are not very meaningful in that example, but
their order may very well be. Depends on the map! In practice for the
towns map the -c flag would be used to suppress the numbers.

> I generally agree with introducing these tricks (clever decision making,
> heuristics). However, in this case it is questionable if it creates more
> confusion then convenient/handy behavior.

I don't think the two flipping triggers I mentioned cause any confusion.
Certainly the rules= way logically flows from the way you type it in, and
the flipped at= order only happens if you know about it.

> Perhaps option order=ascending, order=descending and order=auto would
improve the
> situation by making things explicit. order=auto can be the default.
order=ascending
> and order=descending would disable any handy tricks.

It's over-engineering the problem. Just use the -f flag if you need to.

Claiming author's prerogative and closing as wontfix. I spent many many
hours thinking through these problems and experimenting with this on a
wide range of maps & display sizes, and for better or worse, depending on
your point of view, the current way came out on top.

regards,
Hamish

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2382#comment:6&gt;
GRASS GIS <http://grass.osgeo.org>

#2382: d.legend: integer map legends should not be flipped upside-down
----------------------+-----------------------------------------------------
  Reporter: neteler | Owner: hamish
      Type: defect | Status: closed
  Priority: normal | Milestone: 7.0.0
Component: Display | Version: svn-releasebranch70
Resolution: wontfix | Keywords: d.legend
  Platform: All | Cpu: Unspecified
----------------------+-----------------------------------------------------

Comment(by hamish):

> "smoothed" legend != "gradient" legend

Hi,

I was thinking a bit more about this, maybe a way around the ambiguity of
what kind of data a CELL map contains is for d.legend to test if the
`r.support units=` has been set and has a string length > 0, and if it
contains a value assume it is a continuous gradient map, and so smallest
value on the bottom.

I fear it moves a bit into 'too tricky for its own good' territory, the
existing help text is nicely concise, but apparently what to expect is not
obvious if you haven't read that. I guess since it talks about
"categorical" and not CELL maps, the text wouldn't have to change for a
continuous gradient CELL map? Seems a bit of a stretch & I don't want to
introduce more confusion..

{{{
        Raster maps based on floating point values will
        display smoothed, from greatest to smallest value,
        while categorical raster maps will display in order,
        from top to bottom. Horizontal legends will always
        be smoothed. If the box is defined with inverted y-
        values or an inverted range, the legend will auto-
        matically flip. If this is not the desired result,
        the -f flag may be used to flip it back.
}}}

messy!

Hamish

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2382#comment:7&gt;
GRASS GIS <http://grass.osgeo.org>

#2382: d.legend: integer map legends should not be flipped upside-down
----------------------+-----------------------------------------------------
  Reporter: neteler | Owner: hamish
      Type: defect | Status: closed
  Priority: normal | Milestone: 7.0.0
Component: Display | Version: svn-releasebranch70
Resolution: wontfix | Keywords: d.legend
  Platform: All | Cpu: Unspecified
----------------------+-----------------------------------------------------

Comment(by wenzeslaus):

Replying to [comment:7 hamish]:
> > "smoothed" legend != "gradient" legend
>
> Hi,
>
> I was thinking a bit more about this, maybe a way around the ambiguity
of what kind of data a CELL map contains is for d.legend to test if the
`r.support units=` has been set and has a string length > 0, and if it
contains a value assume it is a continuous gradient map, and so smallest
value on the bottom.
>
This is using map metadata to decide what map means. I quite like it.

> I fear it moves a bit into 'too tricky for its own good' territory, the
existing help text is nicely concise, but apparently what to expect is not
obvious if you haven't read that. I guess since it talks about
"categorical" and not CELL maps, the text wouldn't have to change for a
continuous gradient CELL map? Seems a bit of a stretch & I don't want to
introduce more confusion..

> Raster maps based on floating point values will
> display smoothed, from greatest to smallest value,
> while categorical raster maps will display in order,
> from top to bottom. Horizontal legends will always
> be smoothed. If the box is defined with inverted y-
> values or an inverted range, the legend will auto-
> matically flip. If this is not the desired result,
> the -f flag may be used to flip it back.
>

I think that the requirement is that that the default behavior must be the
most expected thing. Getting smoothed from bottom to top legend for
floating point maps and for maps which have units and the opposite for
categorical is the expected thing. It think that it is clear for us and it
seems also that there is a way to implement it.

However, there should always be a clear way to set what I want if I know
what I want and I'm not sure if the mechanism behind giving expected
behavior will work for me. I'm not sure if the interface is clear enough
for this case. I'm thinking what if I have to program something which
would be using `d.legend` how I will deal with change of legend just
because of slight change of the size of the window.

I never know if `-f` means "flip back if flipped", "flip from bottom-to-
top to top-to-bottom" or "flip to the opposite of what the automatic
mechanism would do". Again, I'm scared of having to program something
which is using the inverted coordinates approach. Only the flipped range
looks quite clear but why then I'm confused we need the other two?

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2382#comment:8&gt;
GRASS GIS <http://grass.osgeo.org>