2
############################################################################
5
# AUTHOR: M. Hamish Bowman, Dept. Marine Science, Otago Univeristy,
7
# PURPOSE: Populate a GRASSRGB column with a color map and data column
8
# Helper script for thematic mapping tasks
10
# COPYRIGHT: (c) 2008 Hamish Bowman, and the GRASS Development Team
11
# This program is free software under the GNU General Public
12
# License (>=v2). Read the file COPYING that comes with GRASS
15
#############################################################################
18
#% description: Set color rules for features in a vector using a numeric attribute column.
19
#% keywords: vector, color table
24
#% gisprompt: old,vector,vector
26
#% description: Name of input vector map
32
#% description: Name of column containing numeric data
33
#% gisprompt: old_dbcolumn,dbcolumn,dbcolumn
39
#% description: Layer number of data column
40
#% gisprompt: old_layer,layer,layer
48
#% description: Name of color column to populate
49
#% gisprompt: old_dbcolumn,dbcolumn,dbcolumn
59
#% description: Manually set range (min,max)
65
#% options: aspect,aspectcolr,bcyr,bgyr,byg,byr,celsius,corine,curvature,differences,elevation,etopo2,evi,gdd,grey,grey1.0,grey255,grey.eq,grey.log,gyr,haxby,ndvi,population,population_dens,precipitation,precipitation_monthly,rainbow,ramp,random,rstcurv,ryb,ryg,sepia,slope,srtm,terrain,wave
66
#% description: Type of color table
74
#% description: Raster map name from which to copy color table
75
#% gisprompt: old,cell,raster
82
#% description: Path to rules file
83
#% gisprompt: old_file,file,input
90
#% label: Dummy raster map name containing color rules for use with d.legend
91
#% description: Use with the -s flag (using this option implies -s)
92
#% gisprompt: new,cell,raster
97
#% description: Save placeholder raster map for use with d.legend
101
#% description: Invert colors
102
#% guisection: Colors
106
## TODO: implement -e (equalized) and -g (logarithmic) methods in r.colors
107
## 'v.db.select column= | wc -l' to set region size (1xLength)
108
## then create r.in.ascii 1xLength matrix with data (WITHOUT uniq)
109
## and run r.colors on that raster map.
111
## v.to.rast, r.colors -g, then parse colr/ file. But that's resolution dependent
114
if [ -z "$GISBASE" ] ; then
115
echo "You must be in GRASS GIS to run this program." 1>&2
119
if [ "$1" != "@ARGS_PARSED@" ] ; then
120
exec g.parser "$0" "$@"
126
if [ -n "$TEMPFILE" ] ; then
127
\rm "$TEMPFILE" "${TEMPFILE}_vcol.sql"
129
eval `g.findfile elem=windows file="tmp_vcolors.$$" | grep '^name='`
130
if [ -n "$name" ] ; then
132
g.remove region="tmp_vcolors.$$" --quiet
134
eval `g.findfile elem=cell file="tmp_colr_$$" | grep '^name='`
135
if [ -n "$name" ] ; then
136
g.remove rast="tmp_colr_$$" --quiet
139
trap "cleanup" 2 3 15
142
### setup enviro vars ###
143
MAPSET=`g.gisenv get=MAPSET`
145
#### does map exist in CURRENT mapset?
146
eval `g.findfile element=vector file="$GIS_OPT_MAP" mapset="$MAPSET"`
147
VECT_MAPSET=`echo "$GIS_OPT_MAP" | grep '@' | cut -f2 -d'@'`
148
if [ -z "$VECT_MAPSET" ] ; then
149
VECT_MAPSET="$MAPSET"
151
if [ ! "$file" ] || [ "$VECT_MAPSET" != "$MAPSET" ] ; then
152
g.message -e "Vector map <$GIS_OPT_MAP> not found in current mapset"
155
VECTOR=`echo "$GIS_OPT_MAP" | cut -f1 -d'@'`
160
# sanity check mutually exclusive color options
162
for OPT in COLOR RASTER RULES ; do
163
eval "OPTNAME=\$GIS_OPT_${OPT}"
164
if [ -n "$OPTNAME" ] ; then
165
CTEST=`expr $CTEST + 1`
168
if [ "$CTEST" -ne 1 ] ; then
169
g.message -e "Pick one of color, rules, or raster options"
173
if [ -n "$GIS_OPT_COLOR" ] ; then
174
#### check the color rule is valid
175
COLOR_OPTS=`ls "$GISBASE/etc/colors/"`
176
COLOR_OPTS="`echo "$COLOR_OPTS" | tr '\n' ' '` random grey.eq grey.log rules"
179
for COLR in $COLOR_OPTS ; do
180
if [ "$COLR" = "$GIS_OPT_COLOR" ] ; then
185
if [ "$HAVE_COLR" -eq 0 ] ; then
186
g.message -e "Invalid color rule <$GIS_OPT_COLOR>"
187
echo " Valid options are: $COLOR_OPTS"
190
elif [ -n "$GIS_OPT_RASTER" ] ; then
191
r.info -r "$GIS_OPT_RASTER" > /dev/null
192
if [ $? -ne 0 ] ; then
193
g.message -e "Unable to open raster map <$GIS_OPT_RASTER>"
196
elif [ -n "$GIS_OPT_RULES" ] ; then
197
if [ ! -r "$GIS_OPT_RULES" ] ; then
198
g.message -e "Unable to read color rules file <$GIS_OPT_RULES>"
205
# check input data column
206
NCOLUMN_TYPE=`v.info -c map="$GIS_OPT_MAP" layer="$GIS_OPT_LAYER" --quiet | grep -i "|$GIS_OPT_COLUMN$" | cut -f1 -d'|'`
207
if [ -z "$NCOLUMN_TYPE" ] ; then
208
g.message -e "Column <$GIS_OPT_COLUMN> not found"
210
elif [ "$NCOLUMN_TYPE" != "INTEGER" ] && [ "$NCOLUMN_TYPE" != "DOUBLE PRECISION" ] ; then
211
g.message -e "Column <$GIS_OPT_COLUMN> is not numeric"
214
#g.message "column <$GIS_OPT_COLUMN> is type [$NCOLUMN_TYPE]"
216
# check if GRASSRGB column exists, make it if it doesn't
217
TABLE=`v.db.connect -gl map="$GIS_OPT_MAP" layer="$GIS_OPT_LAYER" fs="|" | cut -f2 -d'|'`
218
COLUMN_TYPE=`v.info -c map="$GIS_OPT_MAP" layer="$GIS_OPT_LAYER" --quiet | grep -i "|$GIS_OPT_RGB_COLUMN$" | cut -f1 -d'|'`
219
if [ -z "$COLUMN_TYPE" ] ; then
220
# RGB Column not found, create it
221
g.message "Creating column <$GIS_OPT_RGB_COLUMN> ..."
222
v.db.addcol map="$GIS_OPT_MAP" layer="$GIS_OPT_LAYER" column="$GIS_OPT_RGB_COLUMN varchar(11)"
223
if [ $? -ne 0 ] ; then
224
g.message -e "Creating color column"
227
elif [ "$COLUMN_TYPE" != "CHARACTER" -a "$COLUMN_TYPE" != "TEXT" ] ; then
228
g.message -e "Column <$GIS_OPT_RGB_COLUMN> is not of compatible type (found $COLUMN_TYPE)"
231
NUM_CHARS=`db.describe -c "$TABLE" | grep -i " $GIS_OPT_RGB_COLUMN:" | cut -f4 -d':'`
232
if [ "$NUM_CHARS" -lt 11 ] ; then
233
g.message -e "Color column <$GIS_OPT_RGB_COLUMN> is not wide enough (needs 11 characters)"
240
if [ -n "$GIS_OPT_RANGE" ] ; then
241
#order doesn't matter
242
MINVAL=`echo "$GIS_OPT_RANGE" | grep '[[:digit:]]' | grep ',' | cut -f1 -d','`
243
MAXVAL=`echo "$GIS_OPT_RANGE" | grep '[[:digit:]]' | grep ',' | cut -f2 -d','`
245
g.message "Scanning values ..."
246
MINVAL=`v.db.select map="$GIS_OPT_MAP" column="$GIS_OPT_COLUMN" layer="$GIS_OPT_LAYER" | sort -n | grep '^[-0-9]' | head -n 1`
247
MAXVAL=`v.db.select map="$GIS_OPT_MAP" column="$GIS_OPT_COLUMN" layer="$GIS_OPT_LAYER" | sort -n | grep '^[-0-9]' | tail -n 1`
249
g.message -v message=" min=[$MINVAL] max=[$MAXVAL]"
250
if [ -z "$MINVAL" ] || [ -z "$MAXVAL" ] ; then
251
g.message -e "Scanning data range"
256
# setup internal region
257
g.region save="tmp_vcolors.$$"
258
WIND_OVERRIDE="tmp_vcolors.$$"
260
g.region rows=2 cols=2
262
# create dummy raster map
263
if [ "$NCOLUMN_TYPE" = "INTEGER" ] ; then
264
r.mapcalc "tmp_colr_$$ = if( row() == 1, $MINVAL, $MAXVAL)"
266
r.mapcalc "tmp_colr_$$ = double( if( row() == 1, $MINVAL, $MAXVAL) )"
270
if [ -n "$GIS_OPT_COLOR" ] ; then
271
COLOR_CMD="color=$GIS_OPT_COLOR"
272
elif [ -n "$GIS_OPT_RASTER" ] ; then
273
COLOR_CMD="raster=$GIS_OPT_RASTER"
274
elif [ -n "$GIS_OPT_RULES" ] ; then
275
COLOR_CMD="rules=$GIS_OPT_RULES"
277
if [ $GIS_FLAG_N -eq 1 ] ; then
282
r.colors map="tmp_colr_$$" "$COLOR_CMD" $FLIP_FLAG --quiet
286
TEMPFILE="`g.tempfile pid=$$`"
287
if [ $? -ne 0 ] || [ -z "$TEMPFILE" ] ; then
288
g.message -e "Unable to create temporary file"
294
# calculate colors and write SQL command file
295
g.message "Looking up colors ..."
296
v.db.select map="$GIS_OPT_MAP" layer="$GIS_OPT_LAYER" column="$GIS_OPT_COLUMN" | \
297
sort -n | grep '^[-0-9]' | uniq | \
298
r.what.color -i in="tmp_colr_$$" | sed -e 's/: /|/' | grep -v '|\*$' | \
299
( while read LINE ; do
300
#g.message message="LINE=[$LINE]"
301
VALUE=`echo $LINE | cut -f1 -d'|'`
302
COLR=`echo $LINE | cut -f2 -d'|'`
303
echo "UPDATE $TABLE SET $GIS_OPT_RGB_COLUMN = '$COLR' WHERE $GIS_OPT_COLUMN = $VALUE;" >> "${TEMPFILE}_vcol.sql"
307
if [ ! -e "${TEMPFILE}_vcol.sql" ] ; then
308
g.message -e "No values found in color range"
313
# apply SQL commands to update the table with values
314
NUM_RULES=`wc -l < "${TEMPFILE}_vcol.sql"`
315
g.message "Writing $NUM_RULES colors ..."
317
db.execute input="${TEMPFILE}_vcol.sql"
318
if [ $? -ne 0 ] ; then
319
g.message -e "Processing SQL transaction"
325
if [ -n "$GIS_OPT_PLACEHOLDER" ] || [ $GIS_FLAG_S -eq 1 ] ; then
327
if [ -n "$GIS_OPT_PLACEHOLDER" ] ; then
328
DUMMY_NAME="$GIS_OPT_PLACEHOLDER"
330
DUMMY_NAME="vcolors_$$"
333
g.rename rast="tmp_colr_$$","$DUMMY_NAME" --quiet
334
g.message "Raster map containing color rules saved to <$DUMMY_NAME>"
336
# TODO save full v.colors command line history
337
r.support map="$DUMMY_NAME" history="" \
338
source1="vector map=$GIS_OPT_MAP" \
339
source2="column=$GIS_OPT_COLUMN" \
340
title="Dummy raster to use as thematic vector legend" \
341
description="generated by v.colors using r.mapcalc"
342
r.support map="$DUMMY_NAME" \
343
history="RGB saved into <$GIS_OPT_RGB_COLUMN> using <$GIS_OPT_COLOR$GIS_OPT_RASTER$GIS_OPT_RULES>"
345
g.remove rast="tmp_colr_$$" --quiet
350
#v.db.dropcol map=vcol_test col=GRASSRGB
351
#d.vect -a vcol_test icon=basic/circle color=none size=8