main.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. /****************************************************************************
  2. *
  3. * MODULE: r.series.accumulate
  4. * AUTHOR(S): Markus Metz
  5. * Soeren Gebbert
  6. * based on r.series
  7. * PURPOSE: Calculates (accumulated) raster value means, growing degree days
  8. * (GDDs) or Winkler indices from several input maps.
  9. * COPYRIGHT: (C) 2012 by the GRASS Development Team
  10. *
  11. * This program is free software under the GNU General Public
  12. * License (>=v2). Read the file COPYING that comes with GRASS
  13. * for details.
  14. *
  15. *****************************************************************************/
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include <unistd.h>
  19. #include <limits.h>
  20. #include <math.h>
  21. #include <stdio.h>
  22. #include <grass/gis.h>
  23. #include <grass/raster.h>
  24. #include <grass/glocale.h>
  25. #define METHOD_GDD 1
  26. #define METHOD_MEAN 2
  27. #define METHOD_WINKLER 3
  28. #define METHOD_BEDD 4
  29. #define METHOD_HUGLIN 5
  30. struct map_info
  31. {
  32. const char *name;
  33. int fd;
  34. DCELL *buf;
  35. };
  36. struct map_info_out
  37. {
  38. const char *name;
  39. int fd;
  40. void *buf;
  41. };
  42. int main(int argc, char *argv[])
  43. {
  44. struct GModule *module;
  45. struct
  46. {
  47. struct Option *input, *basemap, *file, *output,
  48. *range, *scale, *shift, *lower,
  49. *upper, *limits, *method;
  50. } parm;
  51. struct
  52. {
  53. struct Flag *nulls, *lazy, *float_output;
  54. } flag;
  55. int i;
  56. int num_inputs, max_inputs;
  57. int method;
  58. struct map_info *inputs = NULL;
  59. struct map_info_out *out = NULL;
  60. struct map_info *basemap = NULL;
  61. struct map_info *map_lower = NULL;
  62. struct map_info *map_upper = NULL;
  63. struct History history;
  64. int nrows, ncols;
  65. int row, col;
  66. DCELL lo, hi, tscale, tshift, lower = 10.0, upper = 30.0;
  67. DCELL dcell_null;
  68. RASTER_MAP_TYPE out_type;
  69. int out_size;
  70. char *desc = NULL;
  71. G_gisinit(argv[0]);
  72. module = G_define_module();
  73. G_add_keyword(_("raster"));
  74. G_add_keyword(_("series"));
  75. G_add_keyword(_("accumulation"));
  76. module->description =
  77. _("Makes each output cell value a accumulation"
  78. "function of the values assigned to the corresponding cells "
  79. "in the input raster map layers.");
  80. parm.basemap = G_define_standard_option(G_OPT_R_INPUT);
  81. parm.basemap->key = "basemap";
  82. parm.basemap->description = _("Existing map to be added to output");
  83. parm.basemap->required = NO;
  84. parm.input = G_define_standard_option(G_OPT_R_INPUTS);
  85. parm.input->required = NO;
  86. parm.file = G_define_standard_option(G_OPT_F_INPUT);
  87. parm.file->key = "file";
  88. parm.file->description = _("Input file with raster map names, one per line");
  89. parm.file->required = NO;
  90. parm.output = G_define_standard_option(G_OPT_R_OUTPUT);
  91. parm.output->multiple = NO;
  92. parm.scale = G_define_option();
  93. parm.scale->key = "scale";
  94. parm.scale->type = TYPE_DOUBLE;
  95. parm.scale->answer = "1.0";
  96. parm.scale->required = NO;
  97. parm.scale->description = _("Scale factor for input");
  98. parm.shift = G_define_option();
  99. parm.shift->key = "shift";
  100. parm.shift->type = TYPE_DOUBLE;
  101. parm.shift->answer = "0.0";
  102. parm.shift->required = NO;
  103. parm.shift->description = _("Shift factor for input");
  104. parm.lower = G_define_standard_option(G_OPT_R_INPUT);
  105. parm.lower->key = "lower";
  106. parm.lower->required = NO;
  107. parm.lower->description = _("The raster map specifying the lower accumulation limit, also called baseline");
  108. parm.upper = G_define_standard_option(G_OPT_R_INPUT);
  109. parm.upper->key = "upper";
  110. parm.upper->required = NO;
  111. parm.upper->description = _("The raster map specifying the upper accumulation limit, also called cutoff. Only applied to BEDD computation.");
  112. parm.range = G_define_option();
  113. parm.range->key = "range";
  114. parm.range->type = TYPE_DOUBLE;
  115. parm.range->key_desc = "min,max";
  116. parm.range->description = _("Ignore values outside this range");
  117. parm.limits = G_define_option();
  118. parm.limits->key = "limits";
  119. parm.limits->type = TYPE_DOUBLE;
  120. parm.limits->key_desc = "lower,upper";
  121. parm.limits->answer = "10,30";
  122. parm.limits->description = _("Use these limits in case lower and/or upper input maps are not defined");
  123. parm.method = G_define_option();
  124. parm.method->key = "method";
  125. parm.method->type = TYPE_STRING;
  126. parm.method->multiple = NO;
  127. parm.method->required = NO;
  128. parm.method->options = "gdd,bedd,huglin,mean";
  129. parm.method->answer = "gdd";
  130. parm.method->label = "This method will be applied to compute the accumulative values from the input maps";
  131. G_asprintf(&desc,
  132. "gdd;%s;mean;%s;bedd;%s;huglin;%s",
  133. _("Growing Degree Days or Winkler indices"),
  134. _("Mean: sum(input maps)/(number of input maps)"),
  135. _("Biologically Effective Degree Days"),
  136. _("Huglin Heliothermal index"));
  137. parm.method->descriptions = desc;
  138. flag.nulls = G_define_flag();
  139. flag.nulls->key = 'n';
  140. flag.nulls->description = _("Propagate NULLs");
  141. flag.lazy = G_define_flag();
  142. flag.lazy->key = 'z';
  143. flag.lazy->description = _("Do not keep files open");
  144. flag.float_output = G_define_flag();
  145. flag.float_output->key = 'f';
  146. flag.float_output->description = _("Create a FCELL map (floating point single precision) as output");
  147. if (G_parser(argc, argv))
  148. exit(EXIT_FAILURE);
  149. lo = -1.0 / 0.0; /* -inf */
  150. hi = 1.0 / 0.0; /* inf */
  151. method = METHOD_GDD;
  152. if (G_strncasecmp(parm.method->answer, "gdd", 3) == 0)
  153. method = METHOD_GDD;
  154. else if (G_strncasecmp(parm.method->answer, "mean", 4) == 0)
  155. method = METHOD_MEAN;
  156. else if (G_strncasecmp(parm.method->answer, "bedd", 4) == 0)
  157. method = METHOD_BEDD;
  158. else if (G_strncasecmp(parm.method->answer, "huglin", 7) == 0)
  159. method = METHOD_HUGLIN;
  160. if (parm.range->answer) {
  161. lo = atof(parm.range->answers[0]);
  162. hi = atof(parm.range->answers[1]);
  163. }
  164. if (parm.limits->answer) {
  165. lower = atof(parm.limits->answers[0]);
  166. upper = atof(parm.limits->answers[1]);
  167. }
  168. if (parm.scale->answer)
  169. tscale = atof(parm.scale->answer);
  170. else
  171. tscale = 1.;
  172. if (parm.shift->answer)
  173. tshift = atof(parm.shift->answer);
  174. else
  175. tshift = 0.;
  176. if (parm.input->answer && parm.file->answer)
  177. G_fatal_error(_("%s= and %s= are mutually exclusive"),
  178. parm.input->key, parm.file->key);
  179. if (!parm.input->answer && !parm.file->answer)
  180. G_fatal_error(_("Please specify %s= or %s="),
  181. parm.input->key, parm.file->key);
  182. max_inputs = 0;
  183. /* process the input maps from the file */
  184. if (parm.file->answer) {
  185. FILE *in;
  186. in = fopen(parm.file->answer, "r");
  187. if (!in)
  188. G_fatal_error(_("Unable to open input file <%s>"),
  189. parm.file->answer);
  190. num_inputs = 0;
  191. for (;;) {
  192. char buf[GNAME_MAX];
  193. char *name;
  194. struct map_info *p;
  195. if (!G_getl2(buf, sizeof(buf), in))
  196. break;
  197. name = G_chop(buf);
  198. /* Ignore empty lines */
  199. if (!*name)
  200. continue;
  201. if (num_inputs >= max_inputs) {
  202. max_inputs += 100;
  203. inputs =
  204. G_realloc(inputs, max_inputs * sizeof(struct map_info));
  205. }
  206. p = &inputs[num_inputs++];
  207. p->name = G_store(name);
  208. G_verbose_message(_("Reading raster map <%s>..."), p->name);
  209. p->buf = Rast_allocate_d_buf();
  210. if (!flag.lazy->answer)
  211. p->fd = Rast_open_old(p->name, "");
  212. }
  213. if (num_inputs < 1)
  214. G_fatal_error(_("No raster map name found in input file"));
  215. fclose(in);
  216. }
  217. else {
  218. for (i = 0; parm.input->answers[i]; i++)
  219. ;
  220. num_inputs = i;
  221. if (num_inputs < 1)
  222. G_fatal_error(_("Raster map not found"));
  223. inputs = G_malloc(num_inputs * sizeof(struct map_info));
  224. for (i = 0; i < num_inputs; i++) {
  225. struct map_info *p = &inputs[i];
  226. p->name = parm.input->answers[i];
  227. G_verbose_message(_("Reading raster map <%s>..."), p->name);
  228. p->buf = Rast_allocate_d_buf();
  229. if (!flag.lazy->answer)
  230. p->fd = Rast_open_old(p->name, "");
  231. }
  232. max_inputs = num_inputs;
  233. }
  234. if (parm.basemap->answer) {
  235. basemap = G_malloc(1 * sizeof(struct map_info));
  236. basemap->name = parm.basemap->answer;
  237. G_verbose_message(_("Reading raster map <%s>..."), basemap->name);
  238. basemap->buf = Rast_allocate_d_buf();
  239. basemap->fd = Rast_open_old(basemap->name, "");
  240. }
  241. if (parm.lower->answer) {
  242. map_lower = G_malloc(1 * sizeof(struct map_info));
  243. map_lower->name = parm.lower->answer;
  244. G_verbose_message(_("Reading raster map <%s>..."), map_lower->name);
  245. map_lower->buf = Rast_allocate_d_buf();
  246. map_lower->fd = Rast_open_old(map_lower->name, "");
  247. }
  248. if (parm.upper->answer) {
  249. map_upper = G_malloc(1 * sizeof(struct map_info));
  250. map_upper->name = parm.upper->answer;
  251. G_verbose_message(_("Reading raster map <%s>..."), map_upper->name);
  252. map_upper->buf = Rast_allocate_d_buf();
  253. map_upper->fd = Rast_open_old(map_upper->name, "");
  254. }
  255. out = G_calloc(1, sizeof(struct map_info_out));
  256. out->name = parm.output->answer;
  257. out_type = flag.float_output->answer ? FCELL_TYPE : DCELL_TYPE;
  258. out->buf = Rast_allocate_buf(out_type);
  259. out_size = Rast_cell_size(out_type);
  260. out->fd = Rast_open_new(out->name, out_type);
  261. nrows = Rast_window_rows();
  262. ncols = Rast_window_cols();
  263. Rast_set_d_null_value(&dcell_null, 1);
  264. /* process the data */
  265. G_verbose_message(_("Percent complete..."));
  266. for (row = 0; row < nrows; row++) {
  267. G_percent(row, nrows, 2);
  268. if (basemap)
  269. Rast_get_d_row(basemap->fd, basemap->buf, row);
  270. if (map_lower)
  271. Rast_get_d_row(map_lower->fd, map_lower->buf, row);
  272. if (map_upper)
  273. Rast_get_d_row(map_upper->fd, map_upper->buf, row);
  274. if (flag.lazy->answer) {
  275. /* Open the files only on run time */
  276. for (i = 0; i < num_inputs; i++) {
  277. inputs[i].fd = Rast_open_old(inputs[i].name, "");
  278. Rast_get_d_row(inputs[i].fd, inputs[i].buf, row);
  279. Rast_close(inputs[i].fd);
  280. }
  281. }
  282. else {
  283. for (i = 0; i < num_inputs; i++)
  284. Rast_get_d_row(inputs[i].fd, inputs[i].buf, row);
  285. }
  286. #pragma omp for schedule (static) private (col)
  287. for (col = 0; col < ncols; col++) {
  288. int null = 0, non_null = 0;
  289. DCELL min, max, avg, value;
  290. if (map_lower)
  291. lower = map_lower->buf[col];
  292. if (map_upper)
  293. upper = map_upper->buf[col];
  294. if (upper <= lower)
  295. G_fatal_error(_("'%s'=%f must be > '%s'=%f"), parm.upper->key, upper,
  296. parm.lower->key, lower);
  297. min = dcell_null;
  298. max = dcell_null;
  299. avg = 0;
  300. for (i = 0; i < num_inputs; i++) {
  301. DCELL v = inputs[i].buf[col];
  302. if (Rast_is_d_null_value(&v))
  303. null = 1;
  304. else {
  305. v = v * tscale + tshift;
  306. if (parm.range->answer && (v < lo || v > hi)) {
  307. null = 1;
  308. }
  309. else {
  310. avg += v;
  311. if (min > v || Rast_is_d_null_value(&min))
  312. min = v;
  313. if (max < v || Rast_is_d_null_value(&max))
  314. max = v;
  315. non_null++;
  316. }
  317. }
  318. }
  319. value = dcell_null;
  320. if (!non_null || (null && flag.nulls->answer)) {
  321. if (basemap)
  322. value = basemap->buf[col];
  323. }
  324. else {
  325. /* Compute mean or index */
  326. avg /= non_null;
  327. switch(method) {
  328. case METHOD_HUGLIN:
  329. avg = (avg + max) / 2;
  330. break;
  331. case METHOD_BEDD:
  332. if(avg > upper)
  333. avg = upper;
  334. break;
  335. case METHOD_MEAN:
  336. value = avg;
  337. break;
  338. default:
  339. /* Winkler or GDD index computation is the default */
  340. break;
  341. }
  342. if (method != METHOD_MEAN) {
  343. value = avg - lower;
  344. if (value < 0.)
  345. value = 0.;
  346. }
  347. if (basemap)
  348. value += basemap->buf[col];
  349. }
  350. Rast_set_d_value((char *)out->buf + col * out_size, value, out_type);
  351. }
  352. Rast_put_row(out->fd, out->buf, out_type);
  353. }
  354. G_percent(row, nrows, 2);
  355. /* close output map */
  356. Rast_close(out->fd);
  357. Rast_short_history(out->name, "raster", &history);
  358. Rast_command_history(&history);
  359. Rast_write_history(out->name, &history);
  360. /* Close input maps */
  361. if (basemap)
  362. Rast_close(basemap->fd);
  363. if (map_lower)
  364. Rast_close(map_lower->fd);
  365. if (map_upper)
  366. Rast_close(map_upper->fd);
  367. if (!flag.lazy->answer) {
  368. for (i = 0; i < num_inputs; i++)
  369. Rast_close(inputs[i].fd);
  370. }
  371. if (method == METHOD_GDD) {
  372. struct Colors colors;
  373. Rast_init_colors(&colors);
  374. Rast_make_colors(&colors, "gdd", 0, 6000);
  375. Rast_write_colors(out->name, G_mapset(), &colors);
  376. }
  377. exit(EXIT_SUCCESS);
  378. }