r.univar_main.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. * r.univar
  3. *
  4. * Calculates univariate statistics from the non-null cells of a GRASS raster map
  5. *
  6. * Copyright (C) 2004-2006 by the GRASS Development Team
  7. * Author(s): Hamish Bowman, University of Otago, New Zealand
  8. * Extended stats: Martin Landa
  9. *
  10. * This program is free software under the GNU General Public
  11. * License (>=v2). Read the file COPYING that comes with GRASS
  12. * for details.
  13. *
  14. * This program is a replacement for the r.univar shell script
  15. */
  16. #include <assert.h>
  17. #include <string.h>
  18. #define MAIN
  19. #include "globals.h"
  20. /* local proto */
  21. void set_params();
  22. /* ************************************************************************* */
  23. /* Set up the arguments we are expecting ********************************** */
  24. /* ************************************************************************* */
  25. void set_params()
  26. {
  27. param.inputfile = G_define_standard_option (G_OPT_R_MAPS);
  28. param.percentile = G_define_option();
  29. param.percentile->key = "percentile";
  30. param.percentile->type = TYPE_INTEGER;
  31. param.percentile->required = NO;
  32. param.percentile->multiple = YES;
  33. param.percentile->options = "0-100";
  34. param.percentile->answer = "90";
  35. param.percentile->description =
  36. _("Percentile to calculate (requires extended statistics flag)");
  37. param.shell_style = G_define_flag();
  38. param.shell_style->key = 'g';
  39. param.shell_style->description = _("Print the stats in shell script style");
  40. param.extended = G_define_flag();
  41. param.extended->key = 'e';
  42. param.extended->description = _("Calculate extended statistics");
  43. return;
  44. }
  45. static int open_raster (const char *infile);
  46. static univar_stat *univar_stat_with_percentiles (int map_type,
  47. int size);
  48. static void process_raster (univar_stat *stats, int fd,
  49. const struct Cell_head *region);
  50. /* *************************************************************** */
  51. /* **** the main functions for r.univar ************************** */
  52. /* *************************************************************** */
  53. int main(int argc, char *argv[])
  54. {
  55. unsigned int rows, cols; /* totals */
  56. int rasters;
  57. struct Cell_head region;
  58. struct GModule *module;
  59. univar_stat *stats;
  60. G_gisinit(argv[0]);
  61. module = G_define_module();
  62. module->keywords = _("raster, statistics");
  63. module->description =
  64. _("Calculates univariate statistics from the non-null cells of a raster map.");
  65. /* Define the different options */
  66. set_params();
  67. if (G_parser(argc, argv))
  68. exit(EXIT_FAILURE);
  69. G_get_window(&region);
  70. rows = region.rows;
  71. cols = region.cols;
  72. /* count the rasters given */
  73. {
  74. const char **p;
  75. for (p = (const char **)param.inputfile->answers, rasters = 0;
  76. *p;
  77. p++, rasters++)
  78. ;
  79. }
  80. /* process them all */
  81. {
  82. size_t cells = rasters * cols * rows;
  83. int map_type = param.extended->answer ? -2 : -1;
  84. char **p;
  85. stats = ((map_type == -1)
  86. ? create_univar_stat_struct (-1, cells, 0)
  87. : 0);
  88. for (p = param.inputfile->answers; *p; p++) {
  89. int fd = open_raster (*p);
  90. if (map_type != -1) {
  91. /* NB: map_type must match when doing extended stats */
  92. int this_type = G_get_raster_map_type (fd);
  93. assert (this_type > -1);
  94. if (map_type < -1) {
  95. assert (stats == 0);
  96. map_type = this_type;
  97. stats = univar_stat_with_percentiles (map_type,
  98. cells);
  99. } else if (this_type != map_type) {
  100. G_fatal_error (_("Raster <%s> type mismatch"), *p);
  101. }
  102. }
  103. process_raster (stats, fd, &region);
  104. }
  105. }
  106. if (!(param.shell_style->answer))
  107. G_percent (rows, rows, 2); /* finish it off */
  108. /* create the output */
  109. print_stats(stats);
  110. /* release memory */
  111. free_univar_stat_struct(stats);
  112. exit(EXIT_SUCCESS);
  113. }
  114. static int
  115. open_raster (const char *infile)
  116. {
  117. char *mapset;
  118. int fd;
  119. mapset = G_find_cell2(infile, "");
  120. if (mapset == NULL) {
  121. G_fatal_error(_("Raster map <%s> not found"), infile);
  122. }
  123. fd = G_open_cell_old(infile, mapset);
  124. if (fd < 0)
  125. G_fatal_error(_("Unable to open raster map <%s>"), infile);
  126. /* . */
  127. return fd;
  128. }
  129. static univar_stat *
  130. univar_stat_with_percentiles (int map_type, int size)
  131. {
  132. univar_stat *stats;
  133. int i;
  134. i = 0;
  135. while(param.percentile->answers[i])
  136. i++;
  137. stats = create_univar_stat_struct (map_type, size, i);
  138. for(i = 0; i < stats->n_perc; i++) {
  139. sscanf(param.percentile->answers[i], "%i", &stats->perc[i]);
  140. }
  141. /* . */
  142. return stats;
  143. }
  144. static void
  145. process_raster (univar_stat *stats, int fd,
  146. const struct Cell_head *region)
  147. {
  148. /* use G_window_rows(), G_window_cols() here? */
  149. const int rows = region->rows;
  150. const int cols = region->cols;
  151. int first = (stats->n < 1);
  152. const RASTER_MAP_TYPE map_type = G_get_raster_map_type (fd);
  153. void *nextp
  154. = ((! param.extended->answer) ? 0
  155. : (map_type == DCELL_TYPE) ? (void *) stats->dcell_array
  156. : (map_type == FCELL_TYPE) ? (void *) stats->fcell_array
  157. : (void *) stats->cell_array);
  158. const size_t value_sz = G_raster_size (map_type);
  159. unsigned int row;
  160. void *raster_row;
  161. raster_row = G_calloc (cols, value_sz);
  162. for (row = 0; row < rows; row++) {
  163. void *ptr;
  164. unsigned int col;
  165. if (G_get_raster_row(fd, raster_row, row, map_type) < 0)
  166. G_fatal_error(_("Reading row %d"), row);
  167. ptr = raster_row;
  168. for (col = 0; col < cols; col++) {
  169. if (G_is_null_value(ptr, map_type)) {
  170. ptr = G_incr_void_ptr (ptr, value_sz);
  171. continue;
  172. }
  173. if (nextp) {
  174. /* put the value into stats->XXXcell_array */
  175. memcpy (nextp, ptr, value_sz);
  176. nextp = G_incr_void_ptr (nextp, value_sz);
  177. }
  178. {
  179. double val
  180. = ((map_type == DCELL_TYPE) ? *((DCELL *) ptr)
  181. : (map_type == FCELL_TYPE) ? *((FCELL *) ptr)
  182. : *((CELL *) ptr));
  183. stats->sum += val;
  184. stats->sumsq += val * val;
  185. stats->sum_abs += fabs (val);
  186. if (first) {
  187. stats->max = val;
  188. stats->min = val;
  189. first = FALSE;
  190. } else {
  191. if (val > stats->max) stats->max = val;
  192. if (val < stats->min) stats->min = val;
  193. }
  194. }
  195. ptr = G_incr_void_ptr (ptr, value_sz);
  196. stats->n++;
  197. }
  198. if (!(param.shell_style->answer))
  199. G_percent(row, rows, 2);
  200. }
  201. }