renyi.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. /****************************************************************************
  2. *
  3. * MODULE: r.li.renyi
  4. *
  5. * PURPOSE: calculates renyi's diversity index
  6. *
  7. * AUTHOR(S): Luca Delucchi, Fondazione Edmund Mach
  8. * Serena Pallecchi student of Computer Science University of Pisa (Italy)
  9. * Rewrite: Markus Metz
  10. *
  11. * COPYRIGHT:
  12. * This program is free software under the GPL (>=v2)
  13. * Read the COPYING file that comes with GRASS for details.
  14. *
  15. ***************************************************************************/
  16. #include <stdlib.h>
  17. #include <fcntl.h>
  18. #include <math.h>
  19. #include <grass/gis.h>
  20. #include <grass/raster.h>
  21. #include <grass/glocale.h>
  22. #include "../r.li.daemon/daemon.h"
  23. #include "../r.li.daemon/avlDefs.h"
  24. #include "../r.li.daemon/avl.h"
  25. /* template is shannon */
  26. rli_func renyi;
  27. int calculate(int fd, struct area_entry *ad, char **par, double *result);
  28. int calculateD(int fd, struct area_entry *ad, char **par, double *result);
  29. int calculateF(int fd, struct area_entry *ad, char **par, double *result);
  30. int main(int argc, char *argv[])
  31. {
  32. struct Option *raster, *conf, *output, *alpha;
  33. struct GModule *module;
  34. char **par = NULL;
  35. G_gisinit(argv[0]);
  36. module = G_define_module();
  37. module->description =
  38. _("Calculates Renyi's diversity index on a raster map");
  39. G_add_keyword(_("raster"));
  40. G_add_keyword(_("landscape structure analysis"));
  41. G_add_keyword(_("diversity index"));
  42. /* define options */
  43. raster = G_define_standard_option(G_OPT_R_INPUT);
  44. conf = G_define_standard_option(G_OPT_F_INPUT);
  45. conf->key = "config";
  46. conf->description = _("Configuration file");
  47. conf->required = YES;
  48. alpha = G_define_option();
  49. alpha->key = "alpha";
  50. alpha->description =
  51. _("Alpha value is the order of the generalized entropy");
  52. alpha->type = TYPE_STRING;
  53. alpha->required = YES;
  54. output = G_define_standard_option(G_OPT_R_OUTPUT);
  55. if (G_parser(argc, argv))
  56. exit(EXIT_FAILURE);
  57. if (atof(alpha->answer) == 1) {
  58. G_fatal_error
  59. ("If alpha = 1 Renyi index is not defined. (Ricotta et al., 2003, Environ. Model. Softw.)");
  60. exit(RLI_ERRORE);
  61. }
  62. else if (atof(alpha->answer) < 0.) {
  63. G_fatal_error
  64. ("Alpha must be > 0 otherwise Renyi index is not defined. (Ricotta et al., 2003, Environ. Model. Softw.)");
  65. exit(RLI_ERRORE);
  66. }
  67. else {
  68. par = &alpha->answer;
  69. }
  70. return calculateIndex(conf->answer, renyi, par, raster->answer,
  71. output->answer);
  72. }
  73. int renyi(int fd, char **par, struct area_entry *ad, double *result)
  74. {
  75. int ris = RLI_OK;
  76. double indice = 0;
  77. if (!par)
  78. G_fatal_error("par is NULL");
  79. switch (ad->data_type) {
  80. case CELL_TYPE:
  81. {
  82. ris = calculate(fd, ad, par, &indice);
  83. break;
  84. }
  85. case DCELL_TYPE:
  86. {
  87. ris = calculateD(fd, ad, par, &indice);
  88. break;
  89. }
  90. case FCELL_TYPE:
  91. {
  92. ris = calculateF(fd, ad, par, &indice);
  93. break;
  94. }
  95. default:
  96. {
  97. G_fatal_error("data type unknown");
  98. return RLI_ERRORE;
  99. }
  100. }
  101. if (ris != RLI_OK) {
  102. return RLI_ERRORE;
  103. }
  104. *result = indice;
  105. return RLI_OK;
  106. }
  107. int calculate(int fd, struct area_entry *ad, char **par, double *result)
  108. {
  109. CELL *buf;
  110. CELL corrCell;
  111. CELL precCell;
  112. int i, j;
  113. int mask_fd = -1, *mask_buf = NULL;
  114. int ris = 0;
  115. int masked = FALSE;
  116. long m = 0;
  117. long tot = 0;
  118. long zero = 0;
  119. long totCorr = 1;
  120. long area = 0;
  121. avl_tree albero = NULL;
  122. AVL_table array;
  123. generic_cell uc;
  124. uc.t = CELL_TYPE;
  125. /* open mask if needed */
  126. if (ad->mask == 1) {
  127. if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
  128. return RLI_ERRORE;
  129. mask_buf = G_malloc(ad->cl * sizeof(int));
  130. if (mask_buf == NULL) {
  131. G_fatal_error("malloc mask_buf failed");
  132. return RLI_ERRORE;
  133. }
  134. masked = TRUE;
  135. }
  136. Rast_set_c_null_value(&precCell, 1);
  137. for (j = 0; j < ad->rl; j++) { /* for each row */
  138. if (masked) {
  139. if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
  140. G_fatal_error("mask read failed");
  141. return RLI_ERRORE;
  142. }
  143. }
  144. buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
  145. for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
  146. corrCell = buf[i + ad->x];
  147. if ((masked) && (mask_buf[i] == 0)) {
  148. Rast_set_c_null_value(&corrCell, 1);
  149. }
  150. if (!(Rast_is_null_value(&corrCell, uc.t))) {
  151. /* total patch area */
  152. area++;
  153. }
  154. if (!(Rast_is_null_value(&precCell, uc.t)) &&
  155. corrCell == precCell) {
  156. totCorr++;
  157. }
  158. else if (!(Rast_is_null_value(&precCell, uc.t)) &&
  159. corrCell != precCell) {
  160. /* add precCell to search tree */
  161. if (albero == NULL) {
  162. uc.val.c = precCell;
  163. albero = avl_make(uc, totCorr);
  164. if (albero == NULL) {
  165. G_fatal_error("avl_make error");
  166. return RLI_ERRORE;
  167. }
  168. m++;
  169. }
  170. else {
  171. uc.val.c = precCell;
  172. ris = avl_add(&albero, uc, totCorr);
  173. switch (ris) {
  174. case AVL_ERR:
  175. {
  176. G_fatal_error("avl_add error");
  177. return RLI_ERRORE;
  178. }
  179. case AVL_ADD:
  180. {
  181. m++;
  182. break;
  183. }
  184. case AVL_PRES:
  185. {
  186. break;
  187. }
  188. default:
  189. {
  190. G_fatal_error("avl_make unknown error");
  191. return RLI_ERRORE;
  192. }
  193. }
  194. }
  195. totCorr = 1;
  196. } /* endif not equal cells */
  197. precCell = corrCell;
  198. }
  199. }
  200. /* last closing */
  201. if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
  202. if (albero == NULL) {
  203. uc.val.c = precCell;
  204. albero = avl_make(uc, totCorr);
  205. if (albero == NULL) {
  206. G_fatal_error("avl_make error");
  207. return RLI_ERRORE;
  208. }
  209. m++;
  210. }
  211. else {
  212. uc.val.c = precCell;
  213. ris = avl_add(&albero, uc, totCorr);
  214. switch (ris) {
  215. case AVL_ERR:
  216. {
  217. G_fatal_error("avl_add error");
  218. return RLI_ERRORE;
  219. }
  220. case AVL_ADD:
  221. {
  222. m++;
  223. break;
  224. }
  225. case AVL_PRES:
  226. {
  227. break;
  228. }
  229. default:
  230. {
  231. G_fatal_error("avl_add unknown error");
  232. return RLI_ERRORE;
  233. }
  234. }
  235. }
  236. }
  237. if (area > 0) {
  238. double alpha;
  239. double pi;
  240. double t;
  241. double sum, sum2;
  242. alpha = atof(par[0]);
  243. array = G_malloc(m * sizeof(AVL_tableRow));
  244. if (array == NULL) {
  245. G_fatal_error("malloc array failed");
  246. return RLI_ERRORE;
  247. }
  248. tot = avl_to_array(albero, zero, array);
  249. if (tot != m) {
  250. G_warning("avl_to_array unexpected value. the result could be wrong");
  251. return RLI_ERRORE;
  252. }
  253. /* calculate renyi index */
  254. sum = 0;
  255. sum2 = 0;
  256. for (i = 0; i < m; i++) {
  257. t = array[i].tot;
  258. pi = t / area;
  259. sum += pow(pi, alpha);
  260. sum2 += pi;
  261. }
  262. G_free(array);
  263. /* correction for numerical instability */
  264. if (sum2 != 1)
  265. sum += 1 - sum2;
  266. if ((alpha < 1 && sum < 1) || (alpha > 1 && sum > 1)) {
  267. G_warning("Renyi index calculation reached numerical instability. "
  268. "This can happen with alpha close to 1. The result will be set to zero.");
  269. sum = 1;
  270. }
  271. *result = (1 / (1 - alpha)) * log(sum);
  272. }
  273. else
  274. Rast_set_d_null_value(result, 1);
  275. avl_destroy(albero);
  276. if (masked) {
  277. close(mask_fd);
  278. G_free(mask_buf);
  279. }
  280. return RLI_OK;
  281. }
  282. int calculateD(int fd, struct area_entry *ad, char **par, double *result)
  283. {
  284. DCELL *buf;
  285. DCELL corrCell;
  286. DCELL precCell;
  287. int i, j;
  288. int mask_fd = -1, *mask_buf = NULL;
  289. int ris = 0;
  290. int masked = FALSE;
  291. long m = 0;
  292. long tot = 0;
  293. long zero = 0;
  294. long totCorr = 1;
  295. long area = 0;
  296. avl_tree albero = NULL;
  297. AVL_table array;
  298. generic_cell uc;
  299. uc.t = DCELL_TYPE;
  300. /* open mask if needed */
  301. if (ad->mask == 1) {
  302. if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
  303. return RLI_ERRORE;
  304. mask_buf = G_malloc(ad->cl * sizeof(int));
  305. if (mask_buf == NULL) {
  306. G_fatal_error("malloc mask_buf failed");
  307. return RLI_ERRORE;
  308. }
  309. masked = TRUE;
  310. }
  311. Rast_set_d_null_value(&precCell, 1);
  312. for (j = 0; j < ad->rl; j++) { /* for each row */
  313. if (masked) {
  314. if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
  315. G_fatal_error("mask read failed");
  316. return RLI_ERRORE;
  317. }
  318. }
  319. buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
  320. for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
  321. corrCell = buf[i + ad->x];
  322. if ((masked) && (mask_buf[i] == 0)) {
  323. Rast_set_d_null_value(&corrCell, 1);
  324. }
  325. if (!(Rast_is_null_value(&corrCell, uc.t))) {
  326. /* total patch area */
  327. area++;
  328. }
  329. if (!(Rast_is_null_value(&precCell, uc.t)) &&
  330. corrCell == precCell) {
  331. totCorr++;
  332. }
  333. else if (!(Rast_is_null_value(&precCell, uc.t)) &&
  334. corrCell != precCell) {
  335. /* add precCell to search tree */
  336. if (albero == NULL) {
  337. uc.val.dc = precCell;
  338. albero = avl_make(uc, totCorr);
  339. if (albero == NULL) {
  340. G_fatal_error("avl_make error");
  341. return RLI_ERRORE;
  342. }
  343. m++;
  344. }
  345. else {
  346. uc.val.dc = precCell;
  347. ris = avl_add(&albero, uc, totCorr);
  348. switch (ris) {
  349. case AVL_ERR:
  350. {
  351. G_fatal_error("avl_add error");
  352. return RLI_ERRORE;
  353. }
  354. case AVL_ADD:
  355. {
  356. m++;
  357. break;
  358. }
  359. case AVL_PRES:
  360. {
  361. break;
  362. }
  363. default:
  364. {
  365. G_fatal_error("avl_make unknown error");
  366. return RLI_ERRORE;
  367. }
  368. }
  369. }
  370. totCorr = 1;
  371. } /* endif not equal cells */
  372. precCell = corrCell;
  373. }
  374. }
  375. /* last closing */
  376. if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
  377. if (albero == NULL) {
  378. uc.val.dc = precCell;
  379. albero = avl_make(uc, totCorr);
  380. if (albero == NULL) {
  381. G_fatal_error("avl_make error");
  382. return RLI_ERRORE;
  383. }
  384. m++;
  385. }
  386. else {
  387. uc.val.dc = precCell;
  388. ris = avl_add(&albero, uc, totCorr);
  389. switch (ris) {
  390. case AVL_ERR:
  391. {
  392. G_fatal_error("avl_add error");
  393. return RLI_ERRORE;
  394. }
  395. case AVL_ADD:
  396. {
  397. m++;
  398. break;
  399. }
  400. case AVL_PRES:
  401. {
  402. break;
  403. }
  404. default:
  405. {
  406. G_fatal_error("avl_add unknown error");
  407. return RLI_ERRORE;
  408. }
  409. }
  410. }
  411. }
  412. if (area > 0) {
  413. double alpha;
  414. double pi;
  415. double t;
  416. double sum, sum2;
  417. alpha = atof(par[0]);
  418. array = G_malloc(m * sizeof(AVL_tableRow));
  419. if (array == NULL) {
  420. G_fatal_error("malloc array failed");
  421. return RLI_ERRORE;
  422. }
  423. tot = avl_to_array(albero, zero, array);
  424. if (tot != m) {
  425. G_warning("avl_to_array unexpected value. the result could be wrong");
  426. return RLI_ERRORE;
  427. }
  428. /* calculate renyi index */
  429. sum = 0;
  430. sum2 = 0;
  431. for (i = 0; i < m; i++) {
  432. t = array[i].tot;
  433. pi = t / area;
  434. sum += pow(pi, alpha);
  435. sum += pi;
  436. }
  437. G_free(array);
  438. /* correction for numerical instability */
  439. if (sum2 != 1)
  440. sum += 1 - sum2;
  441. if ((alpha < 1 && sum < 1) || (alpha > 1 && sum > 1)) {
  442. G_warning("Renyi index calculation reached numerical instability. "
  443. "This can happen with alpha close to 1. The result will be set to zero.");
  444. sum = 1;
  445. }
  446. *result = (1 / (1 - alpha)) * log(sum);
  447. }
  448. else
  449. Rast_set_d_null_value(result, 1);
  450. avl_destroy(albero);
  451. if (masked) {
  452. close(mask_fd);
  453. G_free(mask_buf);
  454. }
  455. return RLI_OK;
  456. }
  457. int calculateF(int fd, struct area_entry *ad, char **par, double *result)
  458. {
  459. FCELL *buf;
  460. FCELL corrCell;
  461. FCELL precCell;
  462. int i, j;
  463. int mask_fd = -1, *mask_buf = NULL;
  464. int ris = 0;
  465. int masked = FALSE;
  466. long m = 0;
  467. long tot = 0;
  468. long zero = 0;
  469. long totCorr = 1;
  470. long area = 0;
  471. avl_tree albero = NULL;
  472. AVL_table array;
  473. generic_cell uc;
  474. uc.t = FCELL_TYPE;
  475. /* open mask if needed */
  476. if (ad->mask == 1) {
  477. if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
  478. return RLI_ERRORE;
  479. mask_buf = G_malloc(ad->cl * sizeof(int));
  480. if (mask_buf == NULL) {
  481. G_fatal_error("malloc mask_buf failed");
  482. return RLI_ERRORE;
  483. }
  484. masked = TRUE;
  485. }
  486. Rast_set_f_null_value(&precCell, 1);
  487. for (j = 0; j < ad->rl; j++) { /* for each row */
  488. if (masked) {
  489. if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
  490. G_fatal_error("mask read failed");
  491. return RLI_ERRORE;
  492. }
  493. }
  494. buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
  495. for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
  496. corrCell = buf[i + ad->x];
  497. if ((masked) && (mask_buf[i] == 0)) {
  498. Rast_set_f_null_value(&corrCell, 1);
  499. }
  500. if (!(Rast_is_null_value(&corrCell, uc.t))) {
  501. /* total patch area */
  502. area++;
  503. }
  504. if (!(Rast_is_null_value(&precCell, uc.t)) &&
  505. corrCell == precCell) {
  506. totCorr++;
  507. }
  508. else if (!(Rast_is_null_value(&precCell, uc.t)) &&
  509. corrCell != precCell) {
  510. /* add precCell to search tree */
  511. if (albero == NULL) {
  512. uc.val.fc = precCell;
  513. albero = avl_make(uc, totCorr);
  514. if (albero == NULL) {
  515. G_fatal_error("avl_make error");
  516. return RLI_ERRORE;
  517. }
  518. m++;
  519. }
  520. else {
  521. uc.val.fc = precCell;
  522. ris = avl_add(&albero, uc, totCorr);
  523. switch (ris) {
  524. case AVL_ERR:
  525. {
  526. G_fatal_error("avl_add error");
  527. return RLI_ERRORE;
  528. }
  529. case AVL_ADD:
  530. {
  531. m++;
  532. break;
  533. }
  534. case AVL_PRES:
  535. {
  536. break;
  537. }
  538. default:
  539. {
  540. G_fatal_error("avl_make unknown error");
  541. return RLI_ERRORE;
  542. }
  543. }
  544. }
  545. totCorr = 1;
  546. } /* endif not equal cells */
  547. precCell = corrCell;
  548. }
  549. }
  550. /* last closing */
  551. if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
  552. if (albero == NULL) {
  553. uc.val.fc = precCell;
  554. albero = avl_make(uc, totCorr);
  555. if (albero == NULL) {
  556. G_fatal_error("avl_make error");
  557. return RLI_ERRORE;
  558. }
  559. m++;
  560. }
  561. else {
  562. uc.val.fc = precCell;
  563. ris = avl_add(&albero, uc, totCorr);
  564. switch (ris) {
  565. case AVL_ERR:
  566. {
  567. G_fatal_error("avl_add error");
  568. return RLI_ERRORE;
  569. }
  570. case AVL_ADD:
  571. {
  572. m++;
  573. break;
  574. }
  575. case AVL_PRES:
  576. {
  577. break;
  578. }
  579. default:
  580. {
  581. G_fatal_error("avl_add unknown error");
  582. return RLI_ERRORE;
  583. }
  584. }
  585. }
  586. }
  587. if (area > 0) {
  588. double alpha;
  589. double pi;
  590. double t;
  591. double sum, sum2;
  592. alpha = atof(par[0]);
  593. array = G_malloc(m * sizeof(AVL_tableRow));
  594. if (array == NULL) {
  595. G_fatal_error("malloc array failed");
  596. return RLI_ERRORE;
  597. }
  598. tot = avl_to_array(albero, zero, array);
  599. if (tot != m) {
  600. G_warning("avl_to_array unexpected value. the result could be wrong");
  601. return RLI_ERRORE;
  602. }
  603. /* calculate renyi index */
  604. sum = 0;
  605. sum2 = 0;
  606. for (i = 0; i < m; i++) {
  607. t = array[i].tot;
  608. pi = t / area;
  609. sum += pow(pi, alpha);
  610. sum2 += pi;
  611. }
  612. G_free(array);
  613. /* correction for numerical instability */
  614. if (sum2 != 1)
  615. sum += 1 - sum2;
  616. if ((alpha < 1 && sum < 1) || (alpha > 1 && sum > 1)) {
  617. G_warning("Renyi index calculation reached numerical instability. "
  618. "This can happen with alpha close to 1. The result will be set to zero.");
  619. sum = 1;
  620. }
  621. *result = (1 / (1 - alpha)) * log(sum);
  622. }
  623. else
  624. Rast_set_d_null_value(result, 1);
  625. avl_destroy(albero);
  626. if (masked) {
  627. close(mask_fd);
  628. G_free(mask_buf);
  629. }
  630. return RLI_OK;
  631. }