[GRASS-dev] d.vect.chart legends

Hi,

I just added a new -l flag to d.vect.chart to output info needed to
create legends for charts. Previously you just got different colors with
no reference to which columns they represented (using default colors).

this can be parsed to make a legend, either using d.graph (like
d.vect.thematic does) or by storing the info in a raster map's metadata
and using d.legend to make the map--for example:

MAP=
COLUMNS=

#### setup temporary file
TMP="`g.tempfile pid=$$`"
if [ $? -ne 0 ] || [ -z "$TMP" ] ; then
    echo "ERROR: unable to create temporary files" 1>&2
    exit 1
fi

d.vect.chart -l map="$MAP" type=point columns="$COLUMNS" > "$TMP"

NCATS=`tail -n1 "$TMP" | cut -f1 -d'|'` # wc -l ?

# create small temporary map hold legend info
g.region save=previous_zoom
g.region n=1 s=0 e=1 w=0 res=1
r.mapcalc "tmp_chart_$$ = $NCATS"
g.region previous_zoom

#set cat labels
eval `g.gisenv`
awk -F'|' '{ printf("%d:%s\n", $1, $2) }' "$TMP" >> \
  "$GISDBASE/$LOCATION_NAME/$MAPSET/cats/tmp_chart_$$"

#set colors
r.colors tmp_chart_$$ color=rules --quiet << EOF
`awk -F'|' '{ printf("%d %s\n", $1, $3) }' "$TMP"`
EOF

#draw the legend
d.legend -c tmp_chart_$$ range=1,$NCATS at=50,90,5,10

enjoy,
Hamish

Hamish,

This is conceptually a nice way for getting legends for a vector map, using
the tools we now have. There have been repeated requests for a way to get
legends for vector maps. Could this be systematized somehow in a script, or
better in the vector code, in some way.

For example, a flag that would automatically create a tiny legend raster
that could be used with d.legend. This could be built out of: the RGB column
for vectors, out of random vector colors, built with a script for
d.vect.thematic (until the C version is done), created for d.vect.chart like
you did for text output.

Michael

On 4/21/07 5:01 AM, "Hamish" <hamish_nospam@yahoo.com> wrote:

Hi,

I just added a new -l flag to d.vect.chart to output info needed to
create legends for charts. Previously you just got different colors with
no reference to which columns they represented (using default colors).

this can be parsed to make a legend, either using d.graph (like
d.vect.thematic does) or by storing the info in a raster map's metadata
and using d.legend to make the map--for example:

MAP=
COLUMNS=

#### setup temporary file
TMP="`g.tempfile pid=$$`"
if [ $? -ne 0 ] || [ -z "$TMP" ] ; then
    echo "ERROR: unable to create temporary files" 1>&2
    exit 1
fi

d.vect.chart -l map="$MAP" type=point columns="$COLUMNS" > "$TMP"

NCATS=`tail -n1 "$TMP" | cut -f1 -d'|'` # wc -l ?

# create small temporary map hold legend info
g.region save=previous_zoom
g.region n=1 s=0 e=1 w=0 res=1
r.mapcalc "tmp_chart_$$ = $NCATS"
g.region previous_zoom

#set cat labels
eval `g.gisenv`
awk -F'|' '{ printf("%d:%s\n", $1, $2) }' "$TMP" >> \
  "$GISDBASE/$LOCATION_NAME/$MAPSET/cats/tmp_chart_$$"

#set colors
r.colors tmp_chart_$$ color=rules --quiet << EOF
`awk -F'|' '{ printf("%d %s\n", $1, $3) }' "$TMP"`
EOF

#draw the legend
d.legend -c tmp_chart_$$ range=1,$NCATS at=50,90,5,10

enjoy,
Hamish

__________________________________________
Michael Barton, Professor of Anthropology
School of Human Evolution & Social Change
Center for Social Dynamics & Complexity
Arizona State University

phone: 480-965-6213
fax: 480-965-7671
www: http://www.public.asu.edu/~cmbarton

Hamish:

> I just added a new -l flag to d.vect.chart to output info needed to
> create legends for charts. Previously you just got different colors
> with no reference to which columns they represented (using default
> colors).
>
> this can be parsed to make a legend, either using d.graph (like
> d.vect.thematic does) or by storing the info in a raster map's
> metadata and using d.legend to make the map

Michael Barton wrote:

This is conceptually a nice way for getting legends for a vector map,
using the tools we now have. There have been repeated requests for a
way to get legends for vector maps. Could this be systematized somehow
in a script, or better in the vector code, in some way.

For example, a flag that would automatically create a tiny legend
raster that could be used with d.legend. This could be built out of:
the RGB column for vectors, out of random vector colors, built with a
script for d.vect.thematic (until the C version is done), created for
d.vect.chart like you did for text output.

I consider the mini-raster map method an Add-on hack- you get lots of
tmp_chart_$$ raster maps left over in your mapset. Not a satisfactory
solution for the main distribution.

I guess the best solution is to add categorical vector legends to
d.legend. This would reuse the integer CELL map legend code to draw
filled boxes[, cat number][, and labels], using cat # and RGBCOLOR
column from a DB table.

Note in the posted script I use the raw column name as the cat label. In
production you'd probably want to edit that to something nicer (eg >10
chars). At least in the d.vect.chart case divining nice labels from the
input vector map isn't really an option, so I'm not sure how to do that
beyond either a) adding an option to d.vect.chart with ';' sep labels,
or b) creating a new DB table from the output of 'd.v.chart -l', then
leave it to the user reset the label column themselves if they want.

Using (b) would mean d.legend didn't care about vector maps, only DB
tables in the form of: "cat|label|color". Which might not be such a bad
solution as it is very flexible. An intermediary shell script awk'ing
v.db.select should be able to create that from a vector map in thematic
cases??? (I've never had the need to do thematic vector mapping in
GRASS, so I can't really appreciate the required dataflow)

Note the d.vect.chart legend is formed from the columns= and colors=
options, not anything to do with the vector map.

Another complication is that I didn't functionalize d.legend when I had
the chance, and now it is a very large and very fragile piece of code.
As it is currently working very well I am a bit loathe to touch it.
I fear to functionalize the module will require a lot of (module) global
variables, which defeats the purpose IMO (result is still logically
messy).

Perhaps start over with a clean legend module/tool/lib fn which takes
"cat|label|color" as input and farm out all rast+vect categorical
legends to that? You'd have to pass on all the rendering info, so it's
still problematic and doesn't gain you much abstraction.

Hamish

Hamish:
> > I just added a new -l flag to d.vect.chart to output info needed
> > to create legends for charts. Previously you just got different
> > colors with no reference to which columns they represented (using
> > default colors).
> >
> > this can be parsed to make a legend, either using d.graph (like
> > d.vect.thematic does) or by storing the info in a raster map's
> > metadata and using d.legend to make the map

Michael:
> This is conceptually a nice way for getting legends for a vector
> map, using the tools we now have. There have been repeated requests
> for a way to get legends for vector maps. Could this be systematized
> somehow in a script, or better in the vector code, in some way.
>
> For example, a flag that would automatically create a tiny legend
> raster that could be used with d.legend. This could be built out of:
> the RGB column for vectors, out of random vector colors, built with
> a script for d.vect.thematic (until the C version is done), created
> for d.vect.chart like you did for text output.

Hamish:

I consider the mini-raster map method an Add-on hack- you get lots of
tmp_chart_$$ raster maps left over in your mapset. Not a satisfactory
solution for the main distribution.

I guess the best solution is to add categorical vector legends to
d.legend. This would reuse the integer CELL map legend code to draw
filled boxes[, cat number][, and labels], using cat # and RGBCOLOR
column from a DB table.

Note in the posted script I use the raw column name as the cat label.
In production you'd probably want to edit that to something nicer (eg
>10
chars). At least in the d.vect.chart case divining nice labels from
the input vector map isn't really an option, so I'm not sure how to do
that beyond either a) adding an option to d.vect.chart with ';' sep
labels, or b) creating a new DB table from the output of 'd.v.chart
-l', then leave it to the user reset the label column themselves if
they want.

Using (b) would mean d.legend didn't care about vector maps, only DB
tables in the form of: "cat|label|color". Which might not be such a
bad solution as it is very flexible. An intermediary shell script
awk'ing v.db.select should be able to create that from a vector map in
thematic cases??? (I've never had the need to do thematic vector
mapping in GRASS, so I can't really appreciate the required dataflow)

Note the d.vect.chart legend is formed from the columns= and colors=
options, not anything to do with the vector map.

Another complication is that I didn't functionalize d.legend when I
had the chance, and now it is a very large and very fragile piece of
code. As it is currently working very well I am a bit loathe to touch
it. I fear to functionalize the module will require a lot of (module)
global variables, which defeats the purpose IMO (result is still
logically messy).

Perhaps start over with a clean legend module/tool/lib fn which takes
"cat|label|color" as input and farm out all rast+vect categorical
legends to that? You'd have to pass on all the rendering info, so it's
still problematic and doesn't gain you much abstraction.

d.legend idea:

if data is fed from stdin (signaled by map=-) create categorical legend
using that data. Data format: "cat|label|color"

e.g.

d.legend -m map="-" <<EOF
1|Main Street|255:0:0
2|Elm Street|0:255:0
3|Old Coach Road|0:0:255
EOF

in this way d.legend could work as a system module by the GUI instead of
a user module, but be useful for non-raster tasks.

question/future: allow smooth FP legends from stdin data for use with
thematic vectors or stick with categorical legends?

Hamish

Good idea. I'd recommend an option for this however. d.legend map=-
data=[file]/[string]

Smooth FP legends would be useful with non-thematic vector maps with many
objects and potential values--points representing K values for soils

Michael

On 4/24/07 12:56 AM, "Hamish" <hamish_nospam@yahoo.com> wrote:

d.legend idea:

if data is fed from stdin (signaled by map=-) create categorical legend
using that data. Data format: "cat|label|color"

e.g.

d.legend -m map="-" <<EOF
1|Main Street|255:0:0
2|Elm Street|0:255:0
3|Old Coach Road|0:0:255
EOF

in this way d.legend could work as a system module by the GUI instead of
a user module, but be useful for non-raster tasks.

question/future: allow smooth FP legends from stdin data for use with
thematic vectors or stick with categorical legends?

__________________________________________
Michael Barton, Professor of Anthropology
School of Human Evolution & Social Change
Center for Social Dynamics & Complexity
Arizona State University

phone: 480-965-6213
fax: 480-965-7671
www: http://www.public.asu.edu/~cmbarton