[GRASS-SVN] r58396 - grass/trunk/raster/r.stats

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Dec 6 07:06:41 PST 2013


Author: martinl
Date: 2013-12-06 07:06:40 -0800 (Fri, 06 Dec 2013)
New Revision: 58396

Modified:
   grass/trunk/raster/r.stats/cell_stats.c
   grass/trunk/raster/r.stats/global.h
   grass/trunk/raster/r.stats/main.c
   grass/trunk/raster/r.stats/r.stats.html
   grass/trunk/raster/r.stats/stats.c
Log:
r.stats: implement 'sort' parameter
         update manual page, add examples
         use G_option_to_separator()


Modified: grass/trunk/raster/r.stats/cell_stats.c
===================================================================
--- grass/trunk/raster/r.stats/cell_stats.c	2013-12-05 18:43:49 UTC (rev 58395)
+++ grass/trunk/raster/r.stats/cell_stats.c	2013-12-06 15:06:40 UTC (rev 58396)
@@ -3,7 +3,7 @@
 #include "global.h"
 
 int cell_stats(int fd[], int with_percents, int with_counts,
-	       int with_areas, int with_labels, char *fmt)
+	       int with_areas, int do_sort, int with_labels, char *fmt)
 {
     CELL **cell;
     int i;
@@ -64,7 +64,7 @@
 
     G_percent(row, nrows, 2);
 
-    sort_cell_stats();
+    sort_cell_stats(do_sort);
     print_cell_stats(fmt, with_percents, with_counts, with_areas, with_labels,
 		     fs);
 

Modified: grass/trunk/raster/r.stats/global.h
===================================================================
--- grass/trunk/raster/r.stats/global.h	2013-12-05 18:43:49 UTC (rev 58395)
+++ grass/trunk/raster/r.stats/global.h	2013-12-06 15:06:40 UTC (rev 58396)
@@ -1,6 +1,10 @@
 #include <grass/gis.h>
 #include <grass/raster.h>
 
+#define SORT_DEFAULT 0
+#define SORT_ASC     1
+#define SORT_DESC    2
+
 extern char *no_data_str;
 extern int nfiles;
 extern int nrows;
@@ -12,11 +16,11 @@
 extern CELL NULL_CELL;
 extern int (*get_row) ();
 
-extern char fs[2];
+extern char *fs;
 extern struct Categories *labels;
 
 /* cell_stats.c */
-int cell_stats(int[], int, int, int, int, char *);
+int cell_stats(int[], int, int, int, int, int, char *);
 
 /* raw_stats.c */
 int raw_stats(int[], int, int, int);
@@ -28,7 +32,6 @@
 void fix_max_fp_val(CELL *, int);
 void reset_null_vals(CELL *, int);
 int update_cell_stats(CELL **, int, double);
-int node_compare(const void *, const void *);
-int sort_cell_stats(void);
+int sort_cell_stats(int);
 int print_node_count(void);
 int print_cell_stats(char *, int, int, int, int, char *);

Modified: grass/trunk/raster/r.stats/main.c
===================================================================
--- grass/trunk/raster/r.stats/main.c	2013-12-05 18:43:49 UTC (rev 58395)
+++ grass/trunk/raster/r.stats/main.c	2013-12-06 15:06:40 UTC (rev 58396)
@@ -7,9 +7,10 @@
  *               Huidae Cho <grass4u gmail.com>, Glynn Clements <glynn gclements.plus.com>,
  *               Hamish Bowman <hamish_b yahoo.com>,
  *               Jachym Cepicky <jachym les-ejk.cz>, Jan-Oliver Wagner <jan intevation.de>
- * PURPOSE:      calculates the area present in each of the categories of
+ *               Sort parameter by Martin Landa <landa.martin gmail.com>
+ * PURPOSE:      Calculates the area present in each of the categories of
  *               user-selected raster map layer(s)
- * COPYRIGHT:    (C) 1999-2006 by the GRASS Development Team
+ * COPYRIGHT:    (C) 1999-2006, 2013 by the GRASS Development Team
  *
  *               This program is free software under the GNU General Public
  *               License (>=v2). Read the file COPYING that comes with GRASS
@@ -21,6 +22,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <grass/glocale.h>
+
 #include "global.h"
 
 char *no_data_str;
@@ -34,14 +36,13 @@
 CELL NULL_CELL;
 int (*get_row) ();
 
-char fs[2];
+char *fs;
 struct Categories *labels;
 
 int main(int argc, char *argv[])
 {
     int *fd;
     char **names;
-    char **ptr;
     char *name;
 
     /* flags */
@@ -52,6 +53,7 @@
     int with_counts;
     int with_areas;
     int with_labels;
+    int do_sort;
 
     /* printf format */
     char fmt[20];
@@ -94,6 +96,7 @@
 				   NOTE: when -C flag is used, and there are 
 				   explicit fp ranges in cats or when the map 
 				   is int, nsteps is ignored */
+        struct Option *sort;    /* sort by cell counts */
     } option;
 
     G_gisinit(argv[0]);
@@ -102,7 +105,7 @@
     G_add_keyword(_("raster"));
     G_add_keyword(_("statistics"));
     module->description =
-	_("Generates area statistics for raster map layers.");
+	_("Generates area statistics for raster map.");
 
     /* Define the different options */
 
@@ -116,6 +119,19 @@
     option.fs = G_define_standard_option(G_OPT_F_SEP);
     option.fs->answer = "space";
 
+    option.sort = G_define_option();
+    option.sort->key = "sort";
+    option.sort->type = TYPE_STRING;
+    option.sort->required = NO;
+    option.sort->multiple = NO;
+    option.sort->label = _("Sort output statistics by cell counts");
+    option.sort->description = _("Default: sorted by categories or intervals)");
+    option.sort->options = "asc,desc";
+    G_asprintf((char **)&(option.sort->descriptions),
+               "asc;%s;desc;%s",
+               _("Sort by cell counts in ascending order"),
+               _("Sort by cell counts in descending order"));
+    
     option.nv = G_define_option();
     option.nv->key = "nv";
     option.nv->type = TYPE_STRING;
@@ -131,19 +147,10 @@
     option.nsteps->multiple = NO;
     option.nsteps->answer = "255";
     option.nsteps->description =
-	_("Number of fp subranges to collect stats from");
+	_("Number of floating-point subranges to collect stats from");
 
     /* Define the different flags */
 
-    flag.one = G_define_flag();
-    flag.one->key = '1';
-    flag.one->description = _("One cell (range) per line");
-
-    flag.A = G_define_flag();
-    flag.A->key = 'A';
-    flag.A->description = _("Print averaged values instead of intervals");
-    flag.A->guisection = _("Print");
-
     flag.a = G_define_flag();
     flag.a->key = 'a';
     flag.a->description = _("Print area totals in square meters");
@@ -151,15 +158,19 @@
 
     flag.c = G_define_flag();
     flag.c->key = 'c';
-    flag.c->description = _("Print cell counts");
+    flag.c->description = _("Print cell counts (sortable)");
     flag.c->guisection = _("Print");
 
     flag.p = G_define_flag();
     flag.p->key = 'p';
     flag.p->description =
-	_("Print APPROXIMATE percents (total percent may not be 100%)");
+	_("Print approximate (total percent may not be 100%) percents");
     flag.p->guisection = _("Print");
 
+    flag.one = G_define_flag();
+    flag.one->key = '1';
+    flag.one->description = _("One cell (range) per line");
+
     flag.l = G_define_flag();
     flag.l->key = 'l';
     flag.l->description = _("Print category labels");
@@ -175,9 +186,14 @@
     flag.x->description = _("Print x and y (column and row)");
     flag.x->guisection = _("Print");
 
+    flag.A = G_define_flag();
+    flag.A->key = 'A';
+    flag.A->description = _("Print averaged values instead of intervals (floating-point maps only)");
+    flag.A->guisection = _("Print");
+
     flag.r = G_define_flag();
     flag.r->key = 'r';
-    flag.r->description = _("Print raw indexes of fp ranges (fp maps only)");
+    flag.r->description = _("Print raw indexes of floating-point ranges (floating-point maps only)");
     flag.r->guisection = _("Print");
 
     flag.n = G_define_flag();
@@ -191,11 +207,11 @@
 
     flag.C = G_define_flag();
     flag.C->key = 'C';
-    flag.C->description = _("Report for cats fp ranges (fp maps only)");
+    flag.C->description = _("Report for cats floating-point ranges (floating-point maps only)");
 
     flag.i = G_define_flag();
     flag.i->key = 'i';
-    flag.i->description = _("Read fp map as integer (use map's quant rules)");
+    flag.i->description = _("Read floating-point map as integer (use map's quant rules)");
 
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
@@ -230,6 +246,22 @@
     with_areas = flag.a->answer;
     with_labels = flag.l->answer;
 
+    /* determine sorting method */
+    do_sort = SORT_DEFAULT; /* sort by cats by default */
+    if (option.sort->answer) {
+        switch(option.sort->answer[0]) {
+        case 'a':
+            do_sort = SORT_ASC;
+            break;
+        case 'd':
+            do_sort = SORT_DESC;
+            break;
+        default:
+            G_debug(1, "Sorting by '%s' not supported", option.sort->answer);
+            break;
+        }
+    }
+
     no_nulls = flag.n->answer;
     no_nulls_all = flag.N->answer;
     no_data_str = option.nv->answer;
@@ -241,28 +273,16 @@
 	raw_data = 1;
 
     /* get field separator */
-    strcpy(fs, " ");
-    if (option.fs->answer) {
-	if (strcmp(option.fs->answer, "space") == 0)
-	    *fs = ' ';
-	else if (strcmp(option.fs->answer, "tab") == 0)
-	    *fs = '\t';
-	else if (strcmp(option.fs->answer, "\\t") == 0)
-	    *fs = '\t';
-	else
-	    *fs = *option.fs->answer;
-    }
+    fs = G_option_to_separator(option.fs);
 
-
     /* open all raster maps */
     if (option.cell->answers[0] == NULL)
 	G_fatal_error(_("Raster map not found"));
 
     names = option.cell->answers;
-    ptr = option.cell->answers;
 
-    for (; *ptr != NULL; ptr++) {
-	name = *ptr;
+    for (; *names != NULL; names++) {
+	name = *names;
 	fd = (int *)G_realloc(fd, (nfiles + 1) * sizeof(int));
 	is_fp = (int *)G_realloc(is_fp, (nfiles + 1) * sizeof(int));
 	DMAX = (DCELL *) G_realloc(DMAX, (nfiles + 1) * sizeof(DCELL));
@@ -350,8 +370,8 @@
     if (raw_data)
 	raw_stats(fd, with_coordinates, with_xy, with_labels);
     else
-	cell_stats(fd, with_percents, with_counts, with_areas, with_labels,
-		   fmt);
+	cell_stats(fd, with_percents, with_counts, with_areas, do_sort,
+                   with_labels, fmt);
 
     exit(EXIT_SUCCESS);
 }

Modified: grass/trunk/raster/r.stats/r.stats.html
===================================================================
--- grass/trunk/raster/r.stats/r.stats.html	2013-12-05 18:43:49 UTC (rev 58395)
+++ grass/trunk/raster/r.stats/r.stats.html	2013-12-06 15:06:40 UTC (rev 58396)
@@ -1,52 +1,59 @@
 <h2>DESCRIPTION</h2>
 
-<em>r.stats</em> calculates the area present in each of the categories of
-user-selected raster map layer(s). Area statistics are given in units of
-square meters and/or cell counts. This analysis uses the current geographic
-region and mask settings. Output can be sent to a file in the user's current
-working directory.
+<em>r.stats</em> calculates the area present in each of the categories
+or floating-point intervals of user-selected <b>input</b> raster map. Area
+statistics are given in units of square meters and/or cell
+counts. This analysis uses the current geographic region
+(<em><a href="g.region.html">g.region</a></em>) and mask settings
+(<em><a href="r.mask.html">r.mask</a></em>). The output statistics can
+be saved to a <b>output</b> file.
 
-If a single map layer is specified on the command line, a list of areas in
-square meters for each category in the raster map layer will be printed. (If
-the <em>-c</em> option is chosen, areas will be stated in number of cells.) If
-multiple raster map layers are specified on the command line, a
-cross-tabulation table of areas for each combination of categories in the map
-layers will be printed.
+<p>
+Area statistics is printed in square meters for each category
+when <b>-a</b> is given. Similarly if <b>-c</b> flag is chosen, areas
+will be stated also in number of cells.
 
-<p>For example, if one raster map layer were specified, the output would look like:
-<pre>
-          1:1350000.00
-          2:4940000.00
-          3:8870000.00
-</pre>
-If three raster map layers <em>a, b</em>, and <em>c</em>, were specified,
-the output would look like:
-<pre>
-          0:0:0:8027500.00
-          0:1:0:1152500.00
-          1:0:0:164227500.00
-          1:0:1:2177500.00
-          1:1:0:140092500.00
-          1:1:1:3355000.00
-          2:0:0:31277500.00
-          2:0:1:2490000.00
-          2:1:0:24207500.00
-          2:1:1:1752500.00
-          3:0:0:17140000.00
-          3:1:0:11270000.00
-          3:1:1:2500.00
-</pre>
-Within each grouping, the first field represents the category  value of map
-layer <em>a</em>, the second represents the category values associated with
-map layer <em>b</em>, the third represents category values for map layer
-<em>c</em>, and the last field gives the area in square meters for the
-particular combination of these three map layers' categories. For example,
-above, combination 3,1,1 covered 2500 square meters. Fields are separated by
-colons.
-
 <h2>NOTES</h2>
-<em>r.stats</em> works in the current geographic region with the current mask.
 
+If a single raster map is specified, a list of categories will be
+printed. If multiple raster maps are specified, a cross-tabulation
+table for each combination of categories in the raster maps will be
+printed.
+
+<p>
+For example, if one raster map was specified, the output would look like:
+<div class="code"><pre>
+1 1350000.00
+2 4940000.00
+3 8870000.00
+</pre></div>
+
+If three raster maps were specified, the output would look like:
+<div class="code"><pre>
+0 0 0 8027500.00
+0 1 0 1152500.00
+1 0 0 164227500.00
+1 0 1 2177500.00
+1 1 0 140092500.00
+1 1 1 3355000.00
+2 0 0 31277500.00
+2 0 1 2490000.00
+2 1 0 24207500.00
+2 1 1 1752500.00
+3 0 0 17140000.00
+3 1 0 11270000.00
+3 1 1 2500.00
+</pre></div>
+
+Within each grouping, the first field represents the category value of
+first raster map, the second represents the category values associated
+with second raster map, the third represents category values for third
+raster map, and the last field gives the area in square meters for the
+particular combination of these three raster maps' categories. For
+example, above, combination 3,1,1 covered 2500 square meters. Fields
+are separated by the <b>separator</b> option.
+
+<!-- do not use bash commands in the manual
 <p>If a nicely formatted output is desired, pipe the output into a command
 which can create columnar output.  For example, the command:
 
@@ -59,26 +66,106 @@
 2:1:1:1090000.00     2:4:1:700000.00      3:1:3:5280000.00
 2:1:3:410000.00      2:4:3:10000.00       3:1:5:3140000.00
 </pre>
+-->
 
-The output from <em>r.stats</em> on more than one map layer is sorted.
+The output from <em>r.stats</em> is sorted by category or category
+intervals (for floating-point raster maps).
 
-<p>Note that the user has only the option of printing out cell statistics in
-terms of cell counts and/or area totals. Users wishing to use different
-units than are available here should use the GRASS program 
-<em><a href="r.report.html">r.report</a></em>.
+<p>
+Note that the user has only the option of printing out cell statistics
+in terms of cell counts and/or area totals. Users wishing to use
+different units than are available here should
+use <em><a href="r.report.html">r.report</a></em>.
 
+<h2>EXAMPLES</h2>
+
+Report area for each category in the single raster map:
+
+<div class="code"><pre>
+r.stats -a in=geology_30m nv=no-data sep=tab
+
+217     71960000.000000
+262     19760000.000000
+270     67760000.000000
+405     25120000.000000
+583     2520000.000000
+720     480000.000000
+766     840000.000000
+862     6560000.000000
+910     4360000.000000
+921     1200000.000000
+946     360000.000000
+948     80000.000000
+no-data 33375200000.000004
+</pre></div>
+
+Report sorted number of cells for each category in the single raster
+map (suppress NULL data):
+
+<div class="code"><pre>
+r.stats -cn in=geology_30m sort=desc
+
+217 1799
+270 1694
+405 628
+262 494
+862 164
+910 109
+583 63
+921 30
+766 21
+720 12
+946 9
+948 2
+</pre></div>
+
+Report area, number of cells, and percents (separated by tabs) for
+each category in the multiple raster maps (suppress NULL data):
+
+<div class="code"><pre>
+r.stats -nacp in=towns,urban sep=tab
+
+1       55      23840000.000000 596     11.89%
+2       55      13680000.000000 342     6.82%
+3       55      1360000.000000  34      0.68%
+4       55      16040000.000000 401     8.00%
+5       55      98240000.000000 2456    48.98%
+6       55      19760000.000000 494     9.85%
+</pre></div>
+
+Report sorted area for each interval of floating-point input raster
+map. Number of intervals are given by <b>nsteps</b> option.
+
+<div class="code"><pre>
+r.stats -an in=elevation nsteps=10 sort=desc sep=tab
+
+95.879221-105.954329    36440000.000000
+85.804114-95.879221     30800000.000000
+105.954329-116.029436   30080000.000000
+116.029436-126.104543   27960000.000000
+126.104543-136.17965    26440000.000000
+136.17965-146.254757    20880000.000000
+75.729007-85.804114     15880000.000000
+65.6539-75.729007       6040000.000000
+146.254757-156.329865   5720000.000000
+55.578793-65.6539       760000.000000
+</pre></div>
+
 <h2>SEE ALSO</h2>
 
 <em>
 <a href="g.region.html">g.region</a>,
+<a href="r.report.html">r.report</a>,
 <a href="r.coin.html">r.coin</a>,
 <a href="r.describe.html">r.describe</a>,
-<a href="r.report.html">r.report</a>,
 <a href="r.statistics.html">r.statistics</a>,
 <a href="r.univar.html">r.univar</a>
 </em>
 
-<h2>AUTHOR</h2>
-Michael Shapiro, U.S. Army Construction Engineering Research Laboratory
+<h2>AUTHORS</h2>
 
-<p><i>Last changed: $Date$</i>
+Michael Shapiro, U.S. Army Construction Engineering Research Laboratory<br>
+Sort option by Martin Landa, Czech Technical University in Prague, 2013
+
+<p>
+<i>Last changed: $Date$</i>

Modified: grass/trunk/raster/r.stats/stats.c
===================================================================
--- grass/trunk/raster/r.stats/stats.c	2013-12-05 18:43:49 UTC (rev 58395)
+++ grass/trunk/raster/r.stats/stats.c	2013-12-06 15:06:40 UTC (rev 58396)
@@ -180,7 +180,7 @@
     return 0;
 }
 
-int node_compare(const void *pp, const void *qq)
+static int node_compare(const void *pp, const void *qq)
 {
     struct Node *const *p = pp, *const *q = qq;
     register int i, x;
@@ -191,22 +191,50 @@
     for (i = nfiles; --i >= 0;)
 	if (x = (*a++ - *b++), x)
 	    return x;
+
     return 0;
 }
 
-int sort_cell_stats(void)
+static int node_compare_count_asc(const void *pp, const void *qq)
 {
+    struct Node *const *p = pp, *const *q = qq;
+    long a, b;
+    
+    a = (*p)->count;
+    b = (*q)->count;
+
+    return (a - b);
+}
+
+static int node_compare_count_desc(const void *pp, const void *qq)
+{
+    struct Node *const *p = pp, *const *q = qq;
+    long a, b;
+    
+    a = (*p)->count;
+    b = (*q)->count;
+
+    return (b - a);
+}
+
+int sort_cell_stats(int do_sort)
+{
     struct Node **q, *p;
 
     if (node_count <= 0)
 	return 0;
 
-    G_free(hashtable);		/* make a bit more room */
+    G_free(hashtable); /* make a bit more room */
     sorted_list = (struct Node **)G_calloc(node_count, sizeof(struct Node *));
     for (q = sorted_list, p = node_list; p; p = p->list)
 	*q++ = p;
 
-    qsort(sorted_list, node_count, sizeof(struct Node *), node_compare);
+    if (do_sort == SORT_DEFAULT)
+        qsort(sorted_list, node_count, sizeof(struct Node *), node_compare);
+    else if (do_sort == SORT_ASC)
+        qsort(sorted_list, node_count, sizeof(struct Node *), node_compare_count_asc);
+    else if (do_sort == SORT_DESC)
+        qsort(sorted_list, node_count, sizeof(struct Node *), node_compare_count_desc);
 
     return 0;
 }
@@ -329,7 +357,7 @@
 	    if (with_counts)
 		fprintf(stdout, "%s%ld", fs, (long)node->count);
 	    if (with_percents)
-		fprintf(stdout, "%s%6.2f%%", fs,
+		fprintf(stdout, "%s%.2f%%", fs,
 			(double)100 * node->count / total_count);
 	    fprintf(stdout, "\n");
 	}



More information about the grass-commit mailing list