[GRASS-SVN] r32235 - grass/trunk/display/d.thematic.area
svn_grass at osgeo.org
svn_grass at osgeo.org
Wed Jul 23 17:26:27 EDT 2008
Author: mlennert
Date: 2008-07-23 17:26:27 -0400 (Wed, 23 Jul 2008)
New Revision: 32235
Modified:
grass/trunk/display/d.thematic.area/Makefile
grass/trunk/display/d.thematic.area/description.html
grass/trunk/display/d.thematic.area/main.c
Log:
added
- possibility to chose algorithm of classification
- option to create a d.graph instructions file for legend
- option to print extended legend info
Modified: grass/trunk/display/d.thematic.area/Makefile
===================================================================
--- grass/trunk/display/d.thematic.area/Makefile 2008-07-23 21:16:34 UTC (rev 32234)
+++ grass/trunk/display/d.thematic.area/Makefile 2008-07-23 21:26:27 UTC (rev 32235)
@@ -3,8 +3,8 @@
PGM = d.thematic.area
-LIBES = $(DISPLAYLIB) $(RASTERLIB) $(VECTLIB) $(DBMILIB) $(GISLIB) $(SYMBLIB)
-DEPENDENCIES = $(DISPLAYDEP) $(RASTERDEP) $(VECTDEP) $(DBMIDEP) $(GISDEP) $(SYMBDEP)
+LIBES = $(ARRAYSTATSLIB) $(DISPLAYLIB) $(RASTERLIB) $(VECTLIB) $(DBMILIB) $(GISLIB) $(SYMBLIB)
+DEPENDENCIES = $(ARRAYSTATSDEP) $(DISPLAYDEP) $(RASTERDEP) $(VECTDEP) $(DBMIDEP) $(GISDEP) $(SYMBDEP)
EXTRA_INC = $(VECT_INC)
EXTRA_CFLAGS = $(VECT_CFLAGS)
Modified: grass/trunk/display/d.thematic.area/description.html
===================================================================
--- grass/trunk/display/d.thematic.area/description.html 2008-07-23 21:16:34 UTC (rev 32234)
+++ grass/trunk/display/d.thematic.area/description.html 2008-07-23 21:26:27 UTC (rev 32235)
@@ -1,10 +1,10 @@
<H2>DESCRIPTION</H2>
-<em>d.thematic.area</em> draws thematic coropleth vector maps based on an attribute column or an expression involving several columns. It takes a number of class breaks (excluding the minimum and maximum values) and a list of colors to apply to the classes (has to be the number of class breaks + 1).
+<em>d.thematic.area</em> draws thematic coropleth vector maps based on an attribute column or an expression involving several columns. It takes a list of class breaks (excluding the minimum and maximum values) and a list of colors to apply to the classes (has to be the number of class breaks + 1).
-The <em>-l</em> flag instructs the module to print legend information (class min | class max | number of observations in class | color) to standard output for futher use in graphical software. When given this flag with the <em>-n</em> flag, the module will only print the legend information without drawing the map.
+Instead of a list of class breaks, the user can also chose a classification algorithm and a number of classes. See the v.class man page for more information on these different algorithms.
-One can used <em>v.class</em> to supply class breaks for d.thematic.area (see example below);
+The <em>-l</em> flag instructs the module to print legend information (class min | class max | number of observations in class | color) to standard output for futher use in graphical software. When combined with the <em>-e</em> flag, the legend information will be extended with some additional statistical information. If the <em>-n</em> flag is set, the module will only print the legend information without drawing the map. If the user gives a <em>legendfile</em>, the module will write d.graph instructions for painting a legend into that file.
<H2>EXAMPLE</H2>
@@ -13,15 +13,16 @@
d.thematic.area -l map=communes3 data=pop breaks=111393.250000,222785.500000,334177.750000 colors=255:0:0,0:255:0,0:0:255,0,0,0
</pre></div>
-The following example uses a calculated attribute (density = pop/area) and v.class to calculate class breaks and feed them directly into d.thematic.area:
+The following example uses a calculated attribute (density = pop/area) and the standard deviation algorithm to calculate class breaks for 5 classes:
<div class="code"><pre>
-d.thematic.area -l map=communes2 data=pop/area breaks=`v.class -g map=communes2 column=pop/area algo=std nbcla=5` colors=0:0:255,50:100:255,255:100:50,255:0:0,156:0:0
+d.thematic.area -l map=communes2 data=pop/area algorithm=std nbclasses=5 colors=0:0:255,50:100:255,255:100:50,255:0:0,156:0:0
</pre></div>
<H2>SEE ALSO</H2>
<EM><A HREF="v.class.html">v.class</A></EM>
<EM><A HREF="d.vect.html">d.vect</A></EM>
+<EM><A HREF="d.graph.html">d.graph</A></EM>
<EM><A HREF="v.univar.html">v.univar</A></EM>
Modified: grass/trunk/display/d.thematic.area/main.c
===================================================================
--- grass/trunk/display/d.thematic.area/main.c 2008-07-23 21:16:34 UTC (rev 32234)
+++ grass/trunk/display/d.thematic.area/main.c 2008-07-23 21:26:27 UTC (rev 32235)
@@ -25,6 +25,7 @@
#include <grass/colors.h>
#include <grass/dbmi.h>
#include <grass/glocale.h>
+#include <grass/arraystats.h>
#include "plot.h"
#include "local_proto.h"
@@ -34,7 +35,7 @@
char *mapset;
int ret, level;
int i, stat = 0;
- int nclass, nbreaks, *frequencies;
+ int nclass = 0, nbreaks, *frequencies, boxsize = 0;
int chcat = 0;
int r, g, b;
int has_color = 0;
@@ -46,16 +47,19 @@
struct Option *map_opt;
struct Option *column_opt;
struct Option *breaks_opt;
+ struct Option *algo_opt;
+ struct Option *nbclass_opt;
struct Option *colors_opt;
struct Option *bcolor_opt;
struct Option *bwidth_opt;
struct Option *where_opt;
struct Option *field_opt;
struct Option *render_opt;
- struct Flag *legend_flag, *x_flag, *nodraw_flag;
+ struct Option *legend_file_opt;
+ struct Flag *legend_flag, *algoinfo_flag, *x_flag, *nodraw_flag;
struct cat_list *Clist;
- int *cats, ncat, nrec;
+ int *cats, ncat, nrec, ctype;
struct Map_info Map;
struct field_info *fi;
dbDriver *driver;
@@ -63,7 +67,9 @@
dbCatValArray cvarr;
struct Cell_head window;
BOUND_BOX box;
- double overlap, *breakpoints, min, max;
+ double overlap, *breakpoints, min = 0, max = 0, *data = NULL, class_info = 0.0;
+ struct GASTATS stats;
+ FILE *fd;
/* Initialize the GIS calls */
G_gisinit(argv[0]);
@@ -86,17 +92,38 @@
breaks_opt = G_define_option();
breaks_opt->key = "breaks";
breaks_opt->type = TYPE_STRING;
- breaks_opt->required = YES;
+ breaks_opt->required = NO;
breaks_opt->multiple = YES;
breaks_opt->description = _("Class breaks, without minimum and maximum");
+ algo_opt = G_define_option();
+ algo_opt->key = "algorithm";
+ algo_opt->type = TYPE_STRING;
+ algo_opt->required = NO;
+ algo_opt->multiple = NO;
+ algo_opt->options = "int,std,qua,equ,dis";
+ algo_opt->description = _("Algorithm to use for classification");
+ algo_opt->descriptions = _("int;simple intervals;"
+ "std;standard deviations;"
+ "qua;quantiles;"
+ "equ;equiprobable (normal distribution);"
+ "dis;discontinuities");
+
+ nbclass_opt = G_define_option();
+ nbclass_opt->key = "nbclasses";
+ nbclass_opt->type = TYPE_INTEGER;
+ nbclass_opt->required = NO;
+ nbclass_opt->multiple = NO;
+ nbclass_opt->description = _("Number of classes to define");
+
colors_opt = G_define_option();
colors_opt->key = "colors";
colors_opt->type = TYPE_STRING;
colors_opt->required = YES;
colors_opt->multiple = YES;
- colors_opt->description = _("Colors (one more than class breaks).");
- colors_opt->gisprompt = GISPROMPT_COLOR;
+ colors_opt->description = _("Colors (one per class).");
+ /* This won't work. We would need multiple color prompt.
+ * colors_opt->gisprompt = GISPROMPT_COLOR; */
field_opt = G_define_standard_option(G_OPT_V_FIELD);
field_opt->description =
@@ -125,7 +152,7 @@
render_opt->type = TYPE_STRING;
render_opt->required = NO;
render_opt->multiple = NO;
- render_opt->answer = "l";
+ render_opt->answer = "c";
render_opt->options = "g,r,d,c,l";
render_opt->description = _("Rendering method for filled polygons");
render_opt->descriptions =
@@ -136,12 +163,23 @@
"l;use the display library culling functions (features: culling, polylines)");
+ legend_file_opt = G_define_standard_option(G_OPT_F_OUTPUT);
+ legend_file_opt->key = "legendfile";
+ legend_file_opt->description =
+ _("File in which to save d.graph instructions for legend display");
+ legend_file_opt->required = NO;
legend_flag = G_define_flag();
legend_flag->key = 'l';
legend_flag->description =
_("Create legend information and send to stdout");
+ algoinfo_flag = G_define_flag();
+ algoinfo_flag->key = 'e';
+ algoinfo_flag->description =
+ _
+ ("When printing legend info , include extended statistical info from classification algorithm");
+
nodraw_flag = G_define_flag();
nodraw_flag->key = 'n';
nodraw_flag->description = _("Do not draw map, only output the legend");
@@ -217,7 +255,7 @@
/*Get CatValArray needed for plotting and for legend calculations */
db_CatValArray_init(&cvarr);
nrec = db_select_CatValArray(driver, fi->table, fi->key,
- column_opt->answer, NULL, &cvarr);
+ column_opt->answer, where_opt->answer, &cvarr);
G_debug(3, "nrec (%s) = %d", column_opt->answer, nrec);
@@ -230,8 +268,6 @@
G_fatal_error(_("Cannot select data (%s) from table"),
column_opt->answer);
- G_debug(2, "\n%d records selected from table", nrec);
-
for (i = 0; i < cvarr.n_values; i++) {
G_debug(4, "cat = %d %s = %d", cvarr.value[i].cat, column_opt->answer,
(cvarr.ctype == DB_C_TYPE_INT ? cvarr.value[i].val.i :
@@ -271,20 +307,90 @@
G_fatal_error(_("Unknown color: [%s]"), bcolor_opt->answer);
}
- /*Get class breaks */
- nbreaks = 0;
- while (breaks_opt->answers[nbreaks] != NULL)
- nbreaks++;
- nclass = nbreaks + 1; /*add one since breaks do not include min and max values */
- G_debug(3, "nclass = %d", nclass);
- breakpoints = (double *)G_malloc((nbreaks) * sizeof(double));
- for (i = 0; i < nbreaks; i++)
- breakpoints[i] = atof(breaks_opt->answers[i]);
+ /* if both class breaks and (algorithm or classnumber) are given, give precedence to class
+ * breaks
+ */
+ if (breaks_opt->answers) {
+
+ if (algo_opt->answer || nbclass_opt->answer)
+ G_warning(_
+ ("You gave both manual breaks and a classification algorithm or a number of classes. The manual breaks have precedence and will thus be used."));
+
+
+ /*Get class breaks */
+ nbreaks = 0;
+ while (breaks_opt->answers[nbreaks] != NULL)
+ nbreaks++;
+ nclass = nbreaks + 1; /*add one since breaks do not include min and max values */
+ G_debug(3, "nclass = %d", nclass);
+
+ breakpoints = (double *)G_malloc((nbreaks) * sizeof(double));
+ for (i = 0; i < nbreaks; i++)
+ breakpoints[i] = atof(breaks_opt->answers[i]);
+
+ }
+ else {
+
+ if (algo_opt->answer && nbclass_opt->answer) {
+
+ ret = db_CatValArray_sort_by_value(&cvarr);
+ if (ret == DB_FAILED)
+ G_fatal_error("Could not sort array of values..");
+
+
+ data = (double *)G_malloc((nrec) * sizeof(double));
+ for (i = 0; i < nrec; i++)
+ data[i] = 0.0;
+
+ ctype = cvarr.ctype;
+ if (ctype == DB_C_TYPE_INT) {
+ for (i = 0; i < nrec; i++)
+ data[i] = cvarr.value[i].val.i;
+ }
+ else {
+ for (i = 0; i < nrec; i++)
+ data[i] = cvarr.value[i].val.d;
+ }
+
+
+ /* min and max are needed later for the legend */
+ if (cvarr.ctype == DB_C_TYPE_INT) {
+ min = cvarr.value[0].val.i;
+ max = cvarr.value[cvarr.n_values - 1].val.i;
+ }
+ else {
+ min = cvarr.value[0].val.d;
+ max = cvarr.value[cvarr.n_values - 1].val.d;
+ }
+
+ nclass = atoi(nbclass_opt->answer);
+ nbreaks = nclass - 1; /* we need one less classbreaks (min and
+ * max exluded) than classes */
+
+ breakpoints = (double *)G_malloc((nbreaks) * sizeof(double));
+ for (i = 0; i < nbreaks; i++)
+ breakpoints[i] = 0;
+
+ /* Get classbreaks for given algorithm and number of classbreaks.
+ * class_info takes any info coming from the classification algorithms */
+ class_info =
+ class_apply_algorithm(algo_opt->answer, data, nrec, &nbreaks,
+ breakpoints);
+
+ }
+ else {
+
+ G_fatal_error(_
+ ("You must either give classbreaks or a classification algrorithm"));
+
+ }
+ };
+
frequencies = (int *)G_malloc((nbreaks + 1) * sizeof(int));
for (i = 0; i < nbreaks + 1; i++)
- frequencies[i] = 0;
+ frequencies[i] = 0;
/* Fill colors */
colors = (struct color_rgb *)G_malloc(nclass * sizeof(struct color_rgb));
@@ -308,79 +414,90 @@
}
+ /* Not sure if this is needed, but probably won't hurt */
+ db_CatValArray_sort(&cvarr);
/* Now's let's prepare the actual plotting */
- if (R_open_driver() != 0)
- G_fatal_error(_("No graphics device selected"));
+ if (R_open_driver() != 0)
+ G_fatal_error(_("No graphics device selected"));
- D_setup(0);
+ D_setup(0);
- G_setup_plot(D_get_d_north(), D_get_d_south(),
- D_get_d_west(), D_get_d_east(), D_move_abs, D_cont_abs);
+ G_setup_plot(D_get_d_north(), D_get_d_south(),
+ D_get_d_west(), D_get_d_east(), D_move_abs, D_cont_abs);
- if (verbose)
- G_message(_("Plotting ..."));
+ if (verbose)
+ G_message(_("Plotting ..."));
- Vect_get_map_box(&Map, &box);
+ Vect_get_map_box(&Map, &box);
- if (window.north < box.S || window.south > box.N ||
- window.east < box.W ||
- window.west > G_adjust_easting(box.E, &window)) {
- G_message(_
- ("The bounding box of the map is outside the current region, "
- "nothing drawn."));
- stat = 0;
- }
- else {
- overlap =
- G_window_percentage_overlap(&window, box.N, box.S, box.E,
- box.W);
- G_debug(1, "overlap = %f \n", overlap);
- if (overlap < 1)
- Vect_set_constraint_region(&Map, window.north, window.south,
- window.east, window.west,
- PORT_DOUBLE_MAX, -PORT_DOUBLE_MAX);
+ if (window.north < box.S || window.south > box.N ||
+ window.east < box.W || window.west > G_adjust_easting(box.E, &window)) {
+ G_message(_
+ ("The bounding box of the map is outside the current region, "
+ "nothing drawn."));
+ stat = 0;
+ }
+ else {
+ overlap =
+ G_window_percentage_overlap(&window, box.N, box.S, box.E, box.W);
+ G_debug(1, "overlap = %f \n", overlap);
+ if (overlap < 1)
+ Vect_set_constraint_region(&Map, window.north, window.south,
+ window.east, window.west,
+ PORT_DOUBLE_MAX, -PORT_DOUBLE_MAX);
- /* default line width */
- D_line_width(default_width);
+ /* default line width */
+ D_line_width(default_width);
- stat = dareatheme(&Map, Clist, &cvarr, breakpoints, nbreaks, colors,
- has_color ? &bcolor : NULL, chcat, &window,
- default_width, frequencies, nodraw_flag->answer);
+ stat = dareatheme(&Map, Clist, &cvarr, breakpoints, nbreaks, colors,
+ has_color ? &bcolor : NULL, chcat, &window,
+ default_width, frequencies, nodraw_flag->answer);
- /* reset line width: Do we need to get line width from display
- * driver (not implemented)? It will help restore previous line
- * width (not just 0) determined by another module (e.g.,
- * d.linewidth). */
- R_line_width(0);
+ /* reset line width: Do we need to get line width from display
+ * driver (not implemented)? It will help restore previous line
+ * width (not just 0) determined by another module (e.g.,
+ * d.linewidth). */
+ R_line_width(0);
- } /* end window check if */
+ } /* end window check if */
- if (!x_flag->answer) {
- D_add_to_list(G_recreate_command());
+ if (!x_flag->answer) {
+ D_add_to_list(G_recreate_command());
- D_set_dig_name(G_fully_qualified_name(map_name, mapset));
- D_add_to_dig_list(G_fully_qualified_name(map_name, mapset));
- }
+ D_set_dig_name(G_fully_qualified_name(map_name, mapset));
+ D_add_to_dig_list(G_fully_qualified_name(map_name, mapset));
+ }
- R_close_driver();
+ R_close_driver();
+
+
if (legend_flag->answer) {
+ if (algoinfo_flag->answer) {
- ret = db_CatValArray_sort_by_value(&cvarr);
- if(cvarr.ctype == DB_C_TYPE_INT) {
- min=cvarr.value[0].val.i;
- max=cvarr.value[cvarr.n_values-1].val.i;
- } else {
- min=cvarr.value[0].val.d;
- max=cvarr.value[cvarr.n_values-1].val.d;
+ basic_stats(data, nrec, &stats);
+
+ fprintf(stdout, _("\nClassification of %s into %i classes\n"),
+ column_opt->answer, nbreaks + 1);
+ fprintf(stdout, _("Using algorithm: *** %s ***\n"),
+ algo_opt->answer);
+ fprintf(stdout, _("Mean: %f\tStandard deviation = %f\n"),
+ stats.mean, stats.stdev);
+
+ if (G_strcasecmp(algo_opt->answer, "dis") == 0)
+ fprintf(stdout, _("Last chi2 = %f\n"), class_info);
+ if (G_strcasecmp(algo_opt->answer, "std") == 0)
+ fprintf(stdout, _("Stdev multiplied by %.4f to define step\n"),
+ class_info);
+ fprintf(stdout, "\n");
+
}
-
fprintf(stdout, "%f|%f|%i|%d:%d:%d\n",
min, breakpoints[0], frequencies[0], colors[0].r, colors[0].g,
colors[0].b);
@@ -392,11 +509,32 @@
}
fprintf(stdout, "%f|%f|%i|%d:%d:%d\n",
breakpoints[nbreaks - 1], max, frequencies[nbreaks],
+ colors[nbreaks].r, colors[nbreaks].g, colors[nbreaks].b);
+ }
+
+ if (legend_file_opt->answer) {
+ fd = fopen(legend_file_opt->answer, "w");
+ boxsize = 100 / nclass;
+ fprintf(fd, "symbol basic/box %i 5 10 black %d:%d:%d\n", boxsize,
colors[0].r, colors[0].g, colors[0].b);
+ fprintf(fd, "move 15 7 \n");
+ fprintf(fd, "text %f - %f\n", min, breakpoints[0]);
+ for (i = 1; i < nbreaks; i++) {
+ fprintf(fd, "symbol basic/box %i 5 %i black %d:%d:%d\n", boxsize,
+ 10 + i * 10, colors[i].r, colors[i].g, colors[i].b);
+ fprintf(fd, "move 15 %i\n", 7 + i * 10);
+ fprintf(fd, "text %f - %f\n", breakpoints[i - 1], breakpoints[i]);
+ }
+ fprintf(fd, "symbol basic/box %i 5 %i black %d:%d:%d\n", boxsize,
+ 10 + i * 10, colors[nbreaks].r, colors[nbreaks].g,
+ colors[nbreaks].b);
+ fprintf(fd, "move 15 %i\n", 7 + i * 10);
+ fprintf(fd, "text %f - %f\n", breakpoints[nbreaks - 1], max);
+ fclose(fd);
}
if (verbose)
- G_done_msg("");
+ G_done_msg(" ");
Vect_close(&Map);
Vect_destroy_cat_list(Clist);
More information about the grass-commit
mailing list