r3.univar_main.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * r3.univar
  3. *
  4. * Calculates univariate statistics from the non-null 3d cells of a raster3d map
  5. *
  6. * Copyright (C) 2004-2007 by the GRASS Development Team
  7. * Author(s): Soeren Gebbert
  8. * Based on r.univar from Hamish Bowman, University of Otago, New Zealand
  9. * and Martin Landa
  10. * heapsort code from http://de.wikipedia.org/wiki/Heapsort
  11. * Zonal stats: Markus Metz
  12. *
  13. * This program is free software under the GNU General Public
  14. * License (>=v2). Read the file COPYING that comes with GRASS
  15. * for details.
  16. *
  17. */
  18. #include <string.h>
  19. #include "globals.h"
  20. #include "grass/raster3d.h"
  21. param_type param;
  22. zone_type zone_info;
  23. /* ************************************************************************* */
  24. /* Set up the arguments we are expecting ********************************** */
  25. /* ************************************************************************* */
  26. void set_params()
  27. {
  28. param.inputfile = G_define_standard_option(G_OPT_R3_MAP);
  29. param.zonefile = G_define_standard_option(G_OPT_R3_INPUT);
  30. param.zonefile->key = "zones";
  31. param.zonefile->required = NO;
  32. param.zonefile->description =
  33. _("3D Raster map used for zoning, must be of type CELL");
  34. param.output_file = G_define_standard_option(G_OPT_F_OUTPUT);
  35. param.output_file->required = NO;
  36. param.output_file->description =
  37. _("Name for output file (if omitted or \"-\" output to stdout)");
  38. param.percentile = G_define_option();
  39. param.percentile->key = "percentile";
  40. param.percentile->type = TYPE_DOUBLE;
  41. param.percentile->required = NO;
  42. param.percentile->multiple = YES;
  43. param.percentile->options = "0-100";
  44. param.percentile->answer = "90";
  45. param.percentile->description =
  46. _("Percentile to calculate (requires extended statistics flag)");
  47. param.separator = G_define_standard_option(G_OPT_F_SEP);
  48. param.shell_style = G_define_flag();
  49. param.shell_style->key = 'g';
  50. param.shell_style->description =
  51. _("Print the stats in shell script style");
  52. param.extended = G_define_flag();
  53. param.extended->key = 'e';
  54. param.extended->description = _("Calculate extended statistics");
  55. param.table = G_define_flag();
  56. param.table->key = 't';
  57. param.table->description = _("Table output format instead of standard output format");
  58. return;
  59. }
  60. /* *************************************************************** */
  61. /* **** the main functions for r3.univar ************************* */
  62. /* *************************************************************** */
  63. int main(int argc, char *argv[])
  64. {
  65. FCELL val_f; /* for misc use */
  66. DCELL val_d; /* for misc use */
  67. int map_type, zmap_type;
  68. univar_stat *stats;
  69. char *infile, *zonemap;
  70. void *map, *zmap = NULL;
  71. RASTER3D_Region region;
  72. unsigned int i;
  73. unsigned int rows, cols, depths;
  74. unsigned int x, y, z;
  75. double dmin, dmax;
  76. int zone, n_zones, use_zone = 0;
  77. const char *mapset, *name;
  78. struct GModule *module;
  79. G_gisinit(argv[0]);
  80. module = G_define_module();
  81. G_add_keyword(_("raster3d"));
  82. G_add_keyword(_("statistics"));
  83. G_add_keyword(_("univariate statistics"));
  84. module->label =
  85. _("Calculates univariate statistics from the non-null cells of a 3D raster map.");
  86. module->description =
  87. _("Statistics include number of cells counted, minimum and maximum cell"
  88. " values, range, arithmetic mean, population variance, standard deviation,"
  89. " coefficient of variation, and sum.");
  90. /* Define the different options */
  91. set_params();
  92. if (G_parser(argc, argv))
  93. exit(EXIT_FAILURE);
  94. /* Set the defaults */
  95. Rast3d_init_defaults();
  96. /* get the current region */
  97. Rast3d_get_window(&region);
  98. cols = region.cols;
  99. rows = region.rows;
  100. depths = region.depths;
  101. name = param.output_file->answer;
  102. if (name != NULL && strcmp(name, "-") != 0) {
  103. if (NULL == freopen(name, "w", stdout)) {
  104. G_fatal_error(_("Unable to open file <%s> for writing"), name);
  105. }
  106. }
  107. /* table field separator */
  108. zone_info.sep = G_option_to_separator(param.separator);
  109. dmin = 0.0 / 0.0; /* set to nan as default */
  110. dmax = 0.0 / 0.0; /* set to nan as default */
  111. zone_info.min = 0.0 / 0.0; /* set to nan as default */
  112. zone_info.max = 0.0 / 0.0; /* set to nan as default */
  113. zone_info.n_zones = 0;
  114. /* open 3D zoning raster with default region */
  115. if ((zonemap = param.zonefile->answer) != NULL) {
  116. if (NULL == (mapset = G_find_raster3d(zonemap, "")))
  117. Rast3d_fatal_error(_("3D raster map <%s> not found"), zonemap);
  118. zmap =
  119. Rast3d_open_cell_old(zonemap, G_find_raster3d(zonemap, ""), &region,
  120. RASTER3D_TILE_SAME_AS_FILE, RASTER3D_USE_CACHE_DEFAULT);
  121. if (zmap == NULL)
  122. Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"), zonemap);
  123. zmap_type = Rast3d_tile_type_map(zmap);
  124. if (Rast3d_read_cats(zonemap, mapset, &(zone_info.cats)))
  125. G_warning("No category support for zoning raster");
  126. Rast3d_range_init(zmap);
  127. Rast3d_range_load(zmap);
  128. Rast3d_range_min_max(zmap, &dmin, &dmax);
  129. /* properly round dmin and dmax */
  130. if (dmin < 0)
  131. zone_info.min = dmin - 0.5;
  132. else
  133. zone_info.min = dmin + 0.5;
  134. if (dmax < 0)
  135. zone_info.max = dmax - 0.5;
  136. else
  137. zone_info.max = dmax + 0.5;
  138. G_debug(1, "min: %d, max: %d", zone_info.min, zone_info.max);
  139. zone_info.n_zones = zone_info.max - zone_info.min + 1;
  140. use_zone = 1;
  141. }
  142. /* Open 3D input raster with default region */
  143. infile = param.inputfile->answer;
  144. if (NULL == G_find_raster3d(infile, ""))
  145. Rast3d_fatal_error(_("3D raster map <%s> not found"), infile);
  146. map =
  147. Rast3d_open_cell_old(infile, G_find_raster3d(infile, ""), &region,
  148. RASTER3D_TILE_SAME_AS_FILE, RASTER3D_USE_CACHE_DEFAULT);
  149. if (map == NULL)
  150. Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"), infile);
  151. map_type = Rast3d_tile_type_map(map);
  152. i = 0;
  153. while (param.percentile->answers[i])
  154. i++;
  155. n_zones = zone_info.n_zones;
  156. if (n_zones == 0)
  157. n_zones = 1;
  158. stats = create_univar_stat_struct(map_type, i);
  159. for (i = 0; i < n_zones; i++) {
  160. unsigned int j;
  161. for (j = 0; j < stats[i].n_perc; j++) {
  162. sscanf(param.percentile->answers[j], "%lf", &(stats[i].perc[j]));
  163. }
  164. }
  165. for (z = 0; z < depths; z++) { /* From the bottom to the top */
  166. if (!(param.shell_style->answer))
  167. G_percent(z, depths - 1, 2);
  168. for (y = 0; y < rows; y++) {
  169. for (x = 0; x < cols; x++) {
  170. zone = 0;
  171. if (zone_info.n_zones) {
  172. if (zmap_type == FCELL_TYPE) {
  173. Rast3d_get_value(zmap, x, y, z, &val_f, FCELL_TYPE);
  174. if (Rast3d_is_null_value_num(&val_f, FCELL_TYPE))
  175. continue;
  176. if (val_f < 0)
  177. zone = val_f - 0.5;
  178. else
  179. zone = val_f + 0.5;
  180. }
  181. else if (zmap_type == DCELL_TYPE) {
  182. Rast3d_get_value(zmap, x, y, z, &val_d, DCELL_TYPE);
  183. if (Rast3d_is_null_value_num(&val_d, DCELL_TYPE))
  184. continue;
  185. if (val_d < 0)
  186. zone = val_d - 0.5;
  187. else
  188. zone = val_d + 0.5;
  189. }
  190. zone -= zone_info.min;
  191. }
  192. if (map_type == FCELL_TYPE) {
  193. Rast3d_get_value(map, x, y, z, &val_f, map_type);
  194. if (!Rast3d_is_null_value_num(&val_f, map_type)) {
  195. if (param.extended->answer) {
  196. if (stats[zone].n >= stats[zone].n_alloc) {
  197. size_t msize;
  198. stats[zone].n_alloc += 1000;
  199. msize = stats[zone].n_alloc * sizeof(FCELL);
  200. stats[zone].fcell_array =
  201. (FCELL *)G_realloc((void *)stats[zone].fcell_array, msize);
  202. }
  203. stats[zone].fcell_array[stats[zone].n] = val_f;
  204. }
  205. stats[zone].sum += val_f;
  206. stats[zone].sumsq += (val_f * val_f);
  207. stats[zone].sum_abs += fabs(val_f);
  208. if (stats[zone].first) {
  209. stats[zone].max = val_f;
  210. stats[zone].min = val_f;
  211. stats[zone].first = FALSE;
  212. }
  213. else {
  214. if (val_f > stats[zone].max)
  215. stats[zone].max = val_f;
  216. if (val_f < stats[zone].min)
  217. stats[zone].min = val_f;
  218. }
  219. stats[zone].n++;
  220. }
  221. stats[zone].size++;
  222. }
  223. else if (map_type == DCELL_TYPE) {
  224. Rast3d_get_value(map, x, y, z, &val_d, map_type);
  225. if (!Rast3d_is_null_value_num(&val_d, map_type)) {
  226. if (param.extended->answer) {
  227. if (stats[zone].n >= stats[zone].n_alloc) {
  228. size_t msize;
  229. stats[zone].n_alloc += 1000;
  230. msize = stats[zone].n_alloc * sizeof(DCELL);
  231. stats[zone].dcell_array =
  232. (DCELL *)G_realloc((void *)stats[zone].dcell_array, msize);
  233. }
  234. stats[zone].dcell_array[stats[zone].n] = val_d;
  235. }
  236. stats[zone].sum += val_d;
  237. stats[zone].sumsq += val_d * val_d;
  238. stats[zone].sum_abs += fabs(val_d);
  239. if (stats[zone].first) {
  240. stats[zone].max = val_d;
  241. stats[zone].min = val_d;
  242. stats[zone].first = FALSE;
  243. }
  244. else {
  245. if (val_d > stats[zone].max)
  246. stats[zone].max = val_d;
  247. if (val_d < stats[zone].min)
  248. stats[zone].min = val_d;
  249. }
  250. stats[zone].n++;
  251. }
  252. stats[zone].size++;
  253. }
  254. }
  255. }
  256. }
  257. /* close maps */
  258. Rast3d_close(map);
  259. if (zone_info.n_zones)
  260. Rast3d_close(zmap);
  261. /* create the output */
  262. if (param.table->answer)
  263. print_stats_table(stats);
  264. else
  265. print_stats(stats);
  266. /* release memory */
  267. free_univar_stat_struct(stats);
  268. exit(EXIT_SUCCESS);
  269. }