r3.univar_main.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  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_INPUT);
  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.separator->description = _("Special characters: space, comma, tab");
  49. param.shell_style = G_define_flag();
  50. param.shell_style->key = 'g';
  51. param.shell_style->description =
  52. _("Print the stats in shell script style");
  53. param.extended = G_define_flag();
  54. param.extended->key = 'e';
  55. param.extended->description = _("Calculate extended statistics");
  56. param.table = G_define_flag();
  57. param.table->key = 't';
  58. param.table->description = _("Table output format instead of standard output format");
  59. return;
  60. }
  61. /* *************************************************************** */
  62. /* **** the main functions for r3.univar ************************* */
  63. /* *************************************************************** */
  64. int main(int argc, char *argv[])
  65. {
  66. FCELL val_f; /* for misc use */
  67. DCELL val_d; /* for misc use */
  68. int map_type, zmap_type;
  69. univar_stat *stats;
  70. char *infile, *zonemap;
  71. void *map, *zmap = NULL;
  72. G3D_Region region;
  73. unsigned int i;
  74. unsigned int rows, cols, depths;
  75. unsigned int x, y, z;
  76. double dmin, dmax;
  77. int zone, n_zones, use_zone = 0;
  78. char *mapset, *name;
  79. struct GModule *module;
  80. G_gisinit(argv[0]);
  81. module = G_define_module();
  82. G_add_keyword(_("raster3d"));
  83. G_add_keyword(_("statistics"));
  84. module->description =
  85. _("Calculates univariate statistics from the non-null 3d cells of a raster3d map.");
  86. /* Define the different options */
  87. set_params();
  88. if (G_parser(argc, argv))
  89. exit(EXIT_FAILURE);
  90. /* Set the defaults */
  91. G3d_initDefaults();
  92. /* get the current region */
  93. G3d_getWindow(&region);
  94. cols = region.cols;
  95. rows = region.rows;
  96. depths = region.depths;
  97. name = param.output_file->answer;
  98. if (name != NULL && strcmp(name, "-") != 0) {
  99. if (NULL == freopen(name, "w", stdout)) {
  100. G_fatal_error(_("Unable to open file <%s> for writing"), name);
  101. }
  102. }
  103. /* table field separator */
  104. zone_info.sep = param.separator->answer;
  105. if (strcmp(zone_info.sep, "\\t") == 0)
  106. zone_info.sep = "\t";
  107. if (strcmp(zone_info.sep, "tab") == 0)
  108. zone_info.sep = "\t";
  109. if (strcmp(zone_info.sep, "space") == 0)
  110. zone_info.sep = " ";
  111. if (strcmp(zone_info.sep, "comma") == 0)
  112. zone_info.sep = ",";
  113. dmin = 0.0 / 0.0; /* set to nan as default */
  114. dmax = 0.0 / 0.0; /* set to nan as default */
  115. zone_info.min = 0.0 / 0.0; /* set to nan as default */
  116. zone_info.max = 0.0 / 0.0; /* set to nan as default */
  117. zone_info.n_zones = 0;
  118. /* open 3D zoning raster with default region */
  119. if ((zonemap = param.zonefile->answer) != NULL) {
  120. if (NULL == (mapset = G_find_grid3(zonemap, "")))
  121. G3d_fatalError(_("Requested g3d map <%s> not found"), zonemap);
  122. zmap =
  123. G3d_openCellOld(zonemap, G_find_grid3(zonemap, ""), &region,
  124. G3D_TILE_SAME_AS_FILE, G3D_USE_CACHE_DEFAULT);
  125. if (zmap == NULL)
  126. G3d_fatalError(_("Error opening g3d map <%s>"), zonemap);
  127. zmap_type = G3d_tileTypeMap(zmap);
  128. if (G3d_readCats(zonemap, mapset, &(zone_info.cats)))
  129. G_warning("no category support for zoning raster");
  130. G3d_range_init(zmap);
  131. if (!G3d_range_load(zmap))
  132. G_fatal_error(_("Unable it load G3d range"));
  133. G3d_range_min_max(zmap, &dmin, &dmax);
  134. /* properly round dmin and dmax */
  135. if (dmin < 0)
  136. zone_info.min = dmin - 0.5;
  137. else
  138. zone_info.min = dmin + 0.5;
  139. if (dmax < 0)
  140. zone_info.max = dmax - 0.5;
  141. else
  142. zone_info.max = dmax + 0.5;
  143. G_debug(1, "min: %d, max: %d", zone_info.min, zone_info.max);
  144. zone_info.n_zones = zone_info.max - zone_info.min + 1;
  145. use_zone = 1;
  146. }
  147. /* Open 3D input raster with default region */
  148. infile = param.inputfile->answer;
  149. if (NULL == G_find_grid3(infile, ""))
  150. G3d_fatalError(_("Requested g3d map <%s> not found"), infile);
  151. map =
  152. G3d_openCellOld(infile, G_find_grid3(infile, ""), &region,
  153. G3D_TILE_SAME_AS_FILE, G3D_USE_CACHE_DEFAULT);
  154. if (map == NULL)
  155. G3d_fatalError(_("Error opening g3d map <%s>"), infile);
  156. map_type = G3d_tileTypeMap(map);
  157. i = 0;
  158. while (param.percentile->answers[i])
  159. i++;
  160. n_zones = zone_info.n_zones;
  161. if (n_zones == 0)
  162. n_zones = 1;
  163. stats = create_univar_stat_struct(map_type, i);
  164. for (i = 0; i < n_zones; i++) {
  165. unsigned int j;
  166. for (j = 0; j < stats[i].n_perc; j++) {
  167. sscanf(param.percentile->answers[j], "%lf", &(stats[i].perc[j]));
  168. }
  169. }
  170. for (z = 0; z < depths; z++) { /* From the bottom to the top */
  171. if (!(param.shell_style->answer))
  172. G_percent(z, depths - 1, 10);
  173. for (y = 0; y < rows; y++) {
  174. for (x = 0; x < cols; x++) {
  175. zone = 0;
  176. if (zone_info.n_zones) {
  177. if (zmap_type == FCELL_TYPE) {
  178. G3d_getValue(zmap, x, y, z, &val_f, FCELL_TYPE);
  179. if (G3d_isNullValueNum(&val_f, FCELL_TYPE))
  180. continue;
  181. if (val_f < 0)
  182. zone = val_f - 0.5;
  183. else
  184. zone = val_f + 0.5;
  185. }
  186. else if (zmap_type == DCELL_TYPE) {
  187. G3d_getValue(zmap, x, y, z, &val_d, DCELL_TYPE);
  188. if (G3d_isNullValueNum(&val_d, DCELL_TYPE))
  189. continue;
  190. if (val_d < 0)
  191. zone = val_d - 0.5;
  192. else
  193. zone = val_d + 0.5;
  194. }
  195. zone -= zone_info.min;
  196. }
  197. if (map_type == FCELL_TYPE) {
  198. G3d_getValue(map, x, y, z, &val_f, map_type);
  199. if (!G3d_isNullValueNum(&val_f, map_type)) {
  200. if (param.extended->answer) {
  201. if (stats[zone].n >= stats[zone].n_alloc) {
  202. size_t msize;
  203. stats[zone].n_alloc += 1000;
  204. msize = stats[zone].n_alloc * sizeof(FCELL);
  205. stats[zone].fcell_array =
  206. (FCELL *)G_realloc((void *)stats[zone].fcell_array, msize);
  207. }
  208. stats[zone].fcell_array[stats[zone].n] = val_f;
  209. }
  210. stats[zone].sum += val_f;
  211. stats[zone].sumsq += (val_f * val_f);
  212. stats[zone].sum_abs += fabs(val_f);
  213. if (stats[zone].first) {
  214. stats[zone].max = val_f;
  215. stats[zone].min = val_f;
  216. stats[zone].first = FALSE;
  217. }
  218. else {
  219. if (val_f > stats[zone].max)
  220. stats[zone].max = val_f;
  221. if (val_f < stats[zone].min)
  222. stats[zone].min = val_f;
  223. }
  224. stats[zone].n++;
  225. }
  226. stats[zone].size++;
  227. }
  228. else if (map_type == DCELL_TYPE) {
  229. G3d_getValue(map, x, y, z, &val_d, map_type);
  230. if (!G3d_isNullValueNum(&val_d, map_type)) {
  231. if (param.extended->answer) {
  232. if (stats[zone].n >= stats[zone].n_alloc) {
  233. size_t msize;
  234. stats[zone].n_alloc += 1000;
  235. msize = stats[zone].n_alloc * sizeof(DCELL);
  236. stats[zone].dcell_array =
  237. (DCELL *)G_realloc((void *)stats[zone].dcell_array, msize);
  238. }
  239. stats[zone].dcell_array[stats[zone].n] = val_d;
  240. }
  241. stats[zone].sum += val_d;
  242. stats[zone].sumsq += val_d * val_d;
  243. stats[zone].sum_abs += fabs(val_d);
  244. if (stats[zone].first) {
  245. stats[zone].max = val_d;
  246. stats[zone].min = val_d;
  247. stats[zone].first = FALSE;
  248. }
  249. else {
  250. if (val_d > stats[zone].max)
  251. stats[zone].max = val_d;
  252. if (val_d < stats[zone].min)
  253. stats[zone].min = val_d;
  254. }
  255. stats[zone].n++;
  256. }
  257. stats[zone].size++;
  258. }
  259. }
  260. }
  261. }
  262. /* close maps */
  263. G3d_closeCell(map);
  264. if (zone_info.n_zones)
  265. G3d_closeCell(zmap);
  266. /* create the output */
  267. if (param.table->answer)
  268. print_stats_table(stats);
  269. else
  270. print_stats(stats);
  271. /* release memory */
  272. free_univar_stat_struct(stats);
  273. exit(EXIT_SUCCESS);
  274. }