r3.univar_main.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  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. 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. module->description =
  84. _("Calculates univariate statistics from the non-null 3d cells of a raster3d map.");
  85. /* Define the different options */
  86. set_params();
  87. if (G_parser(argc, argv))
  88. exit(EXIT_FAILURE);
  89. /* Set the defaults */
  90. Rast3d_init_defaults();
  91. /* get the current region */
  92. Rast3d_get_window(&region);
  93. cols = region.cols;
  94. rows = region.rows;
  95. depths = region.depths;
  96. name = param.output_file->answer;
  97. if (name != NULL && strcmp(name, "-") != 0) {
  98. if (NULL == freopen(name, "w", stdout)) {
  99. G_fatal_error(_("Unable to open file <%s> for writing"), name);
  100. }
  101. }
  102. /* table field separator */
  103. zone_info.sep = param.separator->answer;
  104. if (strcmp(zone_info.sep, "\\t") == 0)
  105. zone_info.sep = "\t";
  106. if (strcmp(zone_info.sep, "tab") == 0)
  107. zone_info.sep = "\t";
  108. if (strcmp(zone_info.sep, "space") == 0)
  109. zone_info.sep = " ";
  110. if (strcmp(zone_info.sep, "comma") == 0)
  111. zone_info.sep = ",";
  112. dmin = 0.0 / 0.0; /* set to nan as default */
  113. dmax = 0.0 / 0.0; /* set to nan as default */
  114. zone_info.min = 0.0 / 0.0; /* set to nan as default */
  115. zone_info.max = 0.0 / 0.0; /* set to nan as default */
  116. zone_info.n_zones = 0;
  117. /* open 3D zoning raster with default region */
  118. if ((zonemap = param.zonefile->answer) != NULL) {
  119. if (NULL == (mapset = G_find_raster3d(zonemap, "")))
  120. Rast3d_fatal_error(_("3D raster map <%s> not found"), zonemap);
  121. zmap =
  122. Rast3d_open_cell_old(zonemap, G_find_raster3d(zonemap, ""), &region,
  123. RASTER3D_TILE_SAME_AS_FILE, RASTER3D_USE_CACHE_DEFAULT);
  124. if (zmap == NULL)
  125. Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"), zonemap);
  126. zmap_type = Rast3d_tile_type_map(zmap);
  127. if (Rast3d_read_cats(zonemap, mapset, &(zone_info.cats)))
  128. G_warning("No category support for zoning raster");
  129. Rast3d_range_init(zmap);
  130. Rast3d_range_load(zmap);
  131. Rast3d_range_min_max(zmap, &dmin, &dmax);
  132. /* properly round dmin and dmax */
  133. if (dmin < 0)
  134. zone_info.min = dmin - 0.5;
  135. else
  136. zone_info.min = dmin + 0.5;
  137. if (dmax < 0)
  138. zone_info.max = dmax - 0.5;
  139. else
  140. zone_info.max = dmax + 0.5;
  141. G_debug(1, "min: %d, max: %d", zone_info.min, zone_info.max);
  142. zone_info.n_zones = zone_info.max - zone_info.min + 1;
  143. use_zone = 1;
  144. }
  145. /* Open 3D input raster with default region */
  146. infile = param.inputfile->answer;
  147. if (NULL == G_find_raster3d(infile, ""))
  148. Rast3d_fatal_error(_("3D raster map <%s> not found"), infile);
  149. map =
  150. Rast3d_open_cell_old(infile, G_find_raster3d(infile, ""), &region,
  151. RASTER3D_TILE_SAME_AS_FILE, RASTER3D_USE_CACHE_DEFAULT);
  152. if (map == NULL)
  153. Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"), infile);
  154. map_type = Rast3d_tile_type_map(map);
  155. i = 0;
  156. while (param.percentile->answers[i])
  157. i++;
  158. n_zones = zone_info.n_zones;
  159. if (n_zones == 0)
  160. n_zones = 1;
  161. stats = create_univar_stat_struct(map_type, i);
  162. for (i = 0; i < n_zones; i++) {
  163. unsigned int j;
  164. for (j = 0; j < stats[i].n_perc; j++) {
  165. sscanf(param.percentile->answers[j], "%lf", &(stats[i].perc[j]));
  166. }
  167. }
  168. for (z = 0; z < depths; z++) { /* From the bottom to the top */
  169. if (!(param.shell_style->answer))
  170. G_percent(z, depths - 1, 10);
  171. for (y = 0; y < rows; y++) {
  172. for (x = 0; x < cols; x++) {
  173. zone = 0;
  174. if (zone_info.n_zones) {
  175. if (zmap_type == FCELL_TYPE) {
  176. Rast3d_get_value(zmap, x, y, z, &val_f, FCELL_TYPE);
  177. if (Rast3d_is_null_value_num(&val_f, FCELL_TYPE))
  178. continue;
  179. if (val_f < 0)
  180. zone = val_f - 0.5;
  181. else
  182. zone = val_f + 0.5;
  183. }
  184. else if (zmap_type == DCELL_TYPE) {
  185. Rast3d_get_value(zmap, x, y, z, &val_d, DCELL_TYPE);
  186. if (Rast3d_is_null_value_num(&val_d, DCELL_TYPE))
  187. continue;
  188. if (val_d < 0)
  189. zone = val_d - 0.5;
  190. else
  191. zone = val_d + 0.5;
  192. }
  193. zone -= zone_info.min;
  194. }
  195. if (map_type == FCELL_TYPE) {
  196. Rast3d_get_value(map, x, y, z, &val_f, map_type);
  197. if (!Rast3d_is_null_value_num(&val_f, map_type)) {
  198. if (param.extended->answer) {
  199. if (stats[zone].n >= stats[zone].n_alloc) {
  200. size_t msize;
  201. stats[zone].n_alloc += 1000;
  202. msize = stats[zone].n_alloc * sizeof(FCELL);
  203. stats[zone].fcell_array =
  204. (FCELL *)G_realloc((void *)stats[zone].fcell_array, msize);
  205. }
  206. stats[zone].fcell_array[stats[zone].n] = val_f;
  207. }
  208. stats[zone].sum += val_f;
  209. stats[zone].sumsq += (val_f * val_f);
  210. stats[zone].sum_abs += fabs(val_f);
  211. if (stats[zone].first) {
  212. stats[zone].max = val_f;
  213. stats[zone].min = val_f;
  214. stats[zone].first = FALSE;
  215. }
  216. else {
  217. if (val_f > stats[zone].max)
  218. stats[zone].max = val_f;
  219. if (val_f < stats[zone].min)
  220. stats[zone].min = val_f;
  221. }
  222. stats[zone].n++;
  223. }
  224. stats[zone].size++;
  225. }
  226. else if (map_type == DCELL_TYPE) {
  227. Rast3d_get_value(map, x, y, z, &val_d, map_type);
  228. if (!Rast3d_is_null_value_num(&val_d, map_type)) {
  229. if (param.extended->answer) {
  230. if (stats[zone].n >= stats[zone].n_alloc) {
  231. size_t msize;
  232. stats[zone].n_alloc += 1000;
  233. msize = stats[zone].n_alloc * sizeof(DCELL);
  234. stats[zone].dcell_array =
  235. (DCELL *)G_realloc((void *)stats[zone].dcell_array, msize);
  236. }
  237. stats[zone].dcell_array[stats[zone].n] = val_d;
  238. }
  239. stats[zone].sum += val_d;
  240. stats[zone].sumsq += val_d * val_d;
  241. stats[zone].sum_abs += fabs(val_d);
  242. if (stats[zone].first) {
  243. stats[zone].max = val_d;
  244. stats[zone].min = val_d;
  245. stats[zone].first = FALSE;
  246. }
  247. else {
  248. if (val_d > stats[zone].max)
  249. stats[zone].max = val_d;
  250. if (val_d < stats[zone].min)
  251. stats[zone].min = val_d;
  252. }
  253. stats[zone].n++;
  254. }
  255. stats[zone].size++;
  256. }
  257. }
  258. }
  259. }
  260. /* close maps */
  261. Rast3d_close(map);
  262. if (zone_info.n_zones)
  263. Rast3d_close(zmap);
  264. /* create the output */
  265. if (param.table->answer)
  266. print_stats_table(stats);
  267. else
  268. print_stats(stats);
  269. /* release memory */
  270. free_univar_stat_struct(stats);
  271. exit(EXIT_SUCCESS);
  272. }