test_r_neighbors.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. from grass.gunittest.case import TestCase
  2. from grass.gunittest.main import test
  3. from grass.script.raster import raster_info
  4. from grass.script import tempfile
  5. class TestNeighbors(TestCase):
  6. """
  7. Used dataset: nc_spm_08_grass7
  8. Test cases:
  9. test_standard_options: Test output with standard options
  10. (size=3, quadratic moving window, standard statistics).
  11. test_standard_options_quantile: Test output with standard options
  12. (size=3, quadratic moving window, quantile statistics).
  13. test_standard_options_circular: Test output with circular neighborhood
  14. (size=7, standard statistics).
  15. test_standard_options_selection: Test output with selection raster
  16. (standard options otherwise).
  17. test_weighting_function: Test results with gaussian weighting
  18. (standard options otherwise).
  19. test_weighting_file: Test results with file for weighting
  20. (standard options otherwise).
  21. """
  22. test_options = {
  23. "test_standard_options": {
  24. "minimum": {
  25. "n": 2025000,
  26. "null_cells": 0,
  27. "cells": 2025000,
  28. "min": 55.5787925720215,
  29. "max": 156.201751708984,
  30. "range": 100.622959136963,
  31. "mean": 109.482040656279,
  32. "mean_of_abs": 109.482040656279,
  33. "stddev": 20.3075456214408,
  34. "variance": 412.3964091669,
  35. "coeff_var": 18.5487459858342,
  36. "sum": 221701132.328964,
  37. },
  38. "perc90": {
  39. "n": 2025000,
  40. "null_cells": 0,
  41. "cells": 2025000,
  42. "min": 56.0450115203857,
  43. "max": 156.317572021484,
  44. "range": 100.272560501099,
  45. "mean": 111.060386339868,
  46. "mean_of_abs": 111.060386339868,
  47. "stddev": 20.301968270214,
  48. "variance": 412.169915644776,
  49. "coeff_var": 18.2801167358501,
  50. "sum": 224897282.338233,
  51. },
  52. "average": {
  53. "n": 2025000,
  54. "null_cells": 0,
  55. "cells": 2025000,
  56. "min": 56.0054066975911,
  57. "max": 156.26158481174,
  58. "range": 100.256178114149,
  59. "mean": 110.375489343136,
  60. "mean_of_abs": 110.375489343136,
  61. "stddev": 20.302357806975,
  62. "variance": 412.18573252244,
  63. "coeff_var": 18.3939006094541,
  64. "sum": 223510365.91985,
  65. },
  66. "maximum": {
  67. "n": 2025000,
  68. "null_cells": 0,
  69. "cells": 2025000,
  70. "min": 56.0526123046875,
  71. "max": 156.329864501953,
  72. "range": 100.277252197266,
  73. "mean": 111.262932473037,
  74. "mean_of_abs": 111.262932473037,
  75. "stddev": 20.2987699017146,
  76. "variance": 412.040059522756,
  77. "coeff_var": 18.2439644997077,
  78. "sum": 225307438.2579,
  79. },
  80. "stddev": {
  81. "n": 2025000,
  82. "null_cells": 0,
  83. "cells": 2025000,
  84. "min": 0,
  85. "max": 6.39749880494391,
  86. "range": 6.39749880494391,
  87. "mean": 0.576904240112151,
  88. "mean_of_abs": 0.576904240112151,
  89. "stddev": 0.440364969041587,
  90. "variance": 0.193921305958998,
  91. "coeff_var": 76.3324202567793,
  92. "sum": 1168231.08622711,
  93. },
  94. "sum": {
  95. "n": 2025000,
  96. "null_cells": 0,
  97. "cells": 2025000,
  98. "min": 233.24821472168,
  99. "max": 1406.35424804688,
  100. "range": 1173.1060333252,
  101. "mean": 992.482567853469,
  102. "mean_of_abs": 992.482567853469,
  103. "stddev": 183.486667152836,
  104. "variance": 33667.3570228558,
  105. "coeff_var": 18.4876463422103,
  106. "sum": 2009777199.90327,
  107. },
  108. },
  109. "test_standard_options_quantile": {
  110. 0.01: {
  111. "n": 2025000,
  112. "null_cells": 0,
  113. "cells": 2025000,
  114. "min": 55.5847009658813,
  115. "max": 156.203791503906,
  116. "range": 100.619090538025,
  117. "mean": 109.503018547944,
  118. "mean_of_abs": 109.503018547944,
  119. "stddev": 20.3076172385226,
  120. "variance": 412.398941046239,
  121. "coeff_var": 18.5452494634586,
  122. "sum": 221743612.559588,
  123. },
  124. 0.03: {
  125. "n": 2025000,
  126. "null_cells": 0,
  127. "cells": 2025000,
  128. "min": 55.5965177536011,
  129. "max": 156.20787109375,
  130. "range": 100.611353340149,
  131. "mean": 109.544974331288,
  132. "mean_of_abs": 109.544974331288,
  133. "stddev": 20.3078125947647,
  134. "variance": 412.407252384084,
  135. "coeff_var": 18.5383334276472,
  136. "sum": 221828573.020859,
  137. },
  138. 0.95: {
  139. "n": 2025000,
  140. "null_cells": 0,
  141. "cells": 2025000,
  142. "min": 56.0488119125366,
  143. "max": 156.323718261719,
  144. "range": 100.274906349182,
  145. "mean": 111.161659406447,
  146. "mean_of_abs": 111.161659406447,
  147. "stddev": 20.3000320258108,
  148. "variance": 412.091300248942,
  149. "coeff_var": 18.2617209334619,
  150. "sum": 225102360.298055,
  151. },
  152. },
  153. "test_standard_options_circular": {
  154. "minimum": {
  155. "n": 2025000,
  156. "null_cells": 0,
  157. "cells": 2025000,
  158. "min": 55.5787925720215,
  159. "max": 155.872573852539,
  160. "range": 100.293781280518,
  161. "mean": 108.457334170361,
  162. "mean_of_abs": 108.457334170361,
  163. "stddev": 20.2561980947474,
  164. "variance": 410.313561253647,
  165. "coeff_var": 18.67665128384,
  166. "sum": 219626101.694981,
  167. },
  168. "perc90": {
  169. "n": 2025000,
  170. "null_cells": 0,
  171. "cells": 2025000,
  172. "min": 56.2710201263428,
  173. "max": 156.299404907227,
  174. "range": 100.028384780884,
  175. "mean": 111.688409057181,
  176. "mean_of_abs": 111.688409057181,
  177. "stddev": 20.286687968792,
  178. "variance": 411.54970874313,
  179. "coeff_var": 18.1636466487815,
  180. "sum": 226169028.340791,
  181. },
  182. "average": {
  183. "n": 2025000,
  184. "null_cells": 0,
  185. "cells": 2025000,
  186. "min": 56.1745609707303,
  187. "max": 156.191996607287,
  188. "range": 100.017435636557,
  189. "mean": 110.375576827845,
  190. "mean_of_abs": 110.375576827845,
  191. "stddev": 20.2777760438563,
  192. "variance": 411.188201284794,
  193. "coeff_var": 18.371615013604,
  194. "sum": 223510543.076386,
  195. },
  196. "maximum": {
  197. "n": 2025000,
  198. "null_cells": 0,
  199. "cells": 2025000,
  200. "min": 56.6209869384766,
  201. "max": 156.329864501953,
  202. "range": 99.7088775634766,
  203. "mean": 112.257478616111,
  204. "mean_of_abs": 112.257478616111,
  205. "stddev": 20.268387328814,
  206. "variance": 410.807524910826,
  207. "coeff_var": 18.0552668549827,
  208. "sum": 227321394.197624,
  209. },
  210. "stddev": {
  211. "n": 2025000,
  212. "null_cells": 0,
  213. "cells": 2025000,
  214. "min": 0,
  215. "max": 9.34457118441325,
  216. "range": 9.34457118441325,
  217. "mean": 1.02915670094965,
  218. "mean_of_abs": 1.02915670094965,
  219. "stddev": 0.682319147525201,
  220. "variance": 0.465559419079517,
  221. "coeff_var": 66.2988587545119,
  222. "sum": 2084042.31942303,
  223. },
  224. },
  225. "test_standard_options_selection": {
  226. "minimum": {
  227. "n": 2025000,
  228. "null_cells": 0,
  229. "cells": 2025000,
  230. "min": 55.5787925720215,
  231. "max": 156.329864501953,
  232. "range": 100.751071929932,
  233. "mean": 110.375440275606,
  234. "mean_of_abs": 110.375440275606,
  235. "stddev": 20.3153233205981,
  236. "variance": 412.712361620436,
  237. "coeff_var": 18.4056555243368,
  238. "sum": 223510266.558102,
  239. },
  240. "perc90": {
  241. "n": 2025000,
  242. "null_cells": 0,
  243. "cells": 2025000,
  244. "min": 55.5787925720215,
  245. "max": 156.329864501953,
  246. "range": 100.751071929932,
  247. "mean": 110.375440275606,
  248. "mean_of_abs": 110.375440275606,
  249. "stddev": 20.3153233205981,
  250. "variance": 412.712361620436,
  251. "coeff_var": 18.4056555243368,
  252. "sum": 223510266.558102,
  253. },
  254. "average": {
  255. "n": 2025000,
  256. "null_cells": 0,
  257. "cells": 2025000,
  258. "min": 55.5787925720215,
  259. "max": 156.329864501953,
  260. "range": 100.751071929932,
  261. "mean": 110.375440275606,
  262. "mean_of_abs": 110.375440275606,
  263. "stddev": 20.3153233205981,
  264. "variance": 412.712361620436,
  265. "coeff_var": 18.4056555243368,
  266. "sum": 223510266.558102,
  267. },
  268. "maximum": {
  269. "n": 2025000,
  270. "null_cells": 0,
  271. "cells": 2025000,
  272. "min": 55.5787925720215,
  273. "max": 156.329864501953,
  274. "range": 100.751071929932,
  275. "mean": 110.375440275606,
  276. "mean_of_abs": 110.375440275606,
  277. "stddev": 20.3153233205981,
  278. "variance": 412.712361620436,
  279. "coeff_var": 18.4056555243368,
  280. "sum": 223510266.558102,
  281. },
  282. "stddev": {
  283. "n": 2025000,
  284. "null_cells": 0,
  285. "cells": 2025000,
  286. "min": 55.5787925720215,
  287. "max": 156.329864501953,
  288. "range": 100.751071929932,
  289. "mean": 110.375440275606,
  290. "mean_of_abs": 110.375440275606,
  291. "stddev": 20.3153233205981,
  292. "variance": 412.712361620436,
  293. "coeff_var": 18.4056555243368,
  294. "sum": 223510266.558102,
  295. },
  296. },
  297. "test_weighting_function": {
  298. "perc90": {
  299. "n": 2025000,
  300. "null_cells": 0,
  301. "cells": 2025000,
  302. "min": 56.4677543640137,
  303. "max": 156.30549621582,
  304. "range": 99.8377418518066,
  305. "mean": 111.789766253374,
  306. "mean_of_abs": 111.789766253374,
  307. "stddev": 20.2825397924116,
  308. "variance": 411.381420430759,
  309. "coeff_var": 18.1434673961486,
  310. "sum": 226374276.663082,
  311. },
  312. "average": {
  313. "n": 2025000,
  314. "null_cells": 0,
  315. "cells": 2025000,
  316. "min": 56.235548348967,
  317. "max": 156.164602692463,
  318. "range": 99.9290543434962,
  319. "mean": 110.375593417834,
  320. "mean_of_abs": 110.375593417834,
  321. "stddev": 20.2736626611521,
  322. "variance": 411.021397698193,
  323. "coeff_var": 18.3678855382501,
  324. "sum": 223510576.671115,
  325. },
  326. "stddev": {
  327. "n": 2025000,
  328. "null_cells": 0,
  329. "cells": 2025000,
  330. "min": 0,
  331. "max": 9.43832203774046,
  332. "range": 9.43832203774046,
  333. "mean": 1.09653550798646,
  334. "mean_of_abs": 1.09653550798646,
  335. "stddev": 0.699381561482314,
  336. "variance": 0.48913456854144,
  337. "coeff_var": 63.7810227200549,
  338. "sum": 2220484.40367258,
  339. },
  340. "sum": {
  341. "n": 2025000,
  342. "null_cells": 0,
  343. "cells": 2025000,
  344. "min": 18.3855979069574,
  345. "max": 133.048299539197,
  346. "range": 114.66270163224,
  347. "mean": 93.868177703987,
  348. "mean_of_abs": 93.868177703987,
  349. "stddev": 17.4006236823834,
  350. "variance": 302.781704535922,
  351. "coeff_var": 18.5372978447033,
  352. "sum": 190083059.850574,
  353. },
  354. },
  355. "test_weighting_file": {
  356. "perc90": {
  357. "n": 2025000,
  358. "null_cells": 0,
  359. "cells": 2025000,
  360. "min": 56.2366943359375,
  361. "max": 156.314498901367,
  362. "range": 100.07780456543,
  363. "mean": 111.666863002851,
  364. "mean_of_abs": 111.666863002851,
  365. "stddev": 20.2890537023546,
  366. "variance": 411.64570013703,
  367. "coeff_var": 18.1692698771673,
  368. "sum": 226125397.580772,
  369. },
  370. "average": {
  371. "n": 2025000,
  372. "null_cells": 0,
  373. "cells": 2025000,
  374. "min": 56.0924235752651,
  375. "max": 156.219111124674,
  376. "range": 100.126687549409,
  377. "mean": 110.375616311748,
  378. "mean_of_abs": 110.375616311748,
  379. "stddev": 20.2776463025833,
  380. "variance": 411.182939572671,
  381. "coeff_var": 18.3714908964228,
  382. "sum": 223510623.03129,
  383. },
  384. "stddev": {
  385. "n": 2025000,
  386. "null_cells": 0,
  387. "cells": 2025000,
  388. "min": 0,
  389. "max": 10.0342267239471,
  390. "range": 10.0342267239471,
  391. "mean": 1.01708477919276,
  392. "mean_of_abs": 1.01708477919276,
  393. "stddev": 0.70410774305486,
  394. "variance": 0.495767713829808,
  395. "coeff_var": 69.2280287208402,
  396. "sum": 2059596.67786534,
  397. },
  398. "sum": {
  399. "n": 2025000,
  400. "null_cells": 0,
  401. "cells": 2025000,
  402. "min": 233.716758728027,
  403. "max": 1874.62933349609,
  404. "range": 1640.91257476807,
  405. "mean": 1322.11428605925,
  406. "mean_of_abs": 1322.11428605925,
  407. "stddev": 245.497028073259,
  408. "variance": 60268.7907928026,
  409. "coeff_var": 18.568517915724,
  410. "sum": 2677281429.26999,
  411. },
  412. },
  413. }
  414. # TODO: replace by unified handing of maps
  415. to_remove = []
  416. def check_univar(self, test_case):
  417. """Checks multiple output against unviariate reference from dict"""
  418. for method in self.test_options[test_case]:
  419. self.assertRasterFitsUnivar(
  420. raster="{}_raster_{}".format(test_case, method),
  421. reference=self.test_options[test_case][method],
  422. precision=1e-5,
  423. )
  424. @classmethod
  425. def setUpClass(cls):
  426. cls.use_temp_region()
  427. cls.runModule("g.region", raster="elevation")
  428. @classmethod
  429. def tearDownClass(cls):
  430. cls.del_temp_region()
  431. if cls.to_remove:
  432. cls.runModule(
  433. "g.remove", flags="f", type="raster", name=",".join(cls.to_remove)
  434. )
  435. def test_standard_options(self):
  436. """Test output with standard options (size=3, quadratic moving window,
  437. standard statistics).
  438. """
  439. test_case = "test_standard_options"
  440. outputs = [
  441. "{}_raster_{}".format(test_case, method)
  442. for method in self.test_options[test_case]
  443. ]
  444. self.to_remove.extend(outputs)
  445. self.assertModule(
  446. "r.neighbors",
  447. input="elevation",
  448. output=",".join(outputs),
  449. method=list(self.test_options[test_case].keys()),
  450. )
  451. self.check_univar(test_case)
  452. def test_standard_options_quantile(self):
  453. """Test output with standard options (size=3, quadratic moving window,
  454. quantile statistics).
  455. """
  456. test_case = "test_standard_options_quantile"
  457. outputs = [
  458. "{}_raster_{}".format(test_case, method)
  459. for method in self.test_options[test_case]
  460. ]
  461. self.to_remove.extend(outputs)
  462. self.assertModule(
  463. "r.neighbors",
  464. input="elevation",
  465. output=",".join(outputs),
  466. method=["quantile"] * len(self.test_options[test_case]),
  467. quantile=list(self.test_options[test_case].keys()),
  468. )
  469. self.check_univar(test_case)
  470. def test_standard_options_circular(self):
  471. """Test output with circular neighborhood (size=7,
  472. standard statistics)."""
  473. test_case = "test_standard_options_circular"
  474. outputs = [
  475. "{}_raster_{}".format(test_case, method)
  476. for method in self.test_options[test_case]
  477. ]
  478. self.to_remove.extend(outputs)
  479. self.assertModule(
  480. "r.neighbors",
  481. flags="c",
  482. input="elevation",
  483. size=7,
  484. output=",".join(outputs),
  485. method=list(self.test_options[test_case].keys()),
  486. )
  487. self.check_univar(test_case)
  488. def test_standard_options_selection(self):
  489. """Test output with selection raster (standard options otherwise)."""
  490. test_case = "test_standard_options_selection"
  491. outputs = [
  492. "{}_raster_{}".format(test_case, method)
  493. for method in self.test_options[test_case]
  494. ]
  495. self.to_remove.extend(outputs)
  496. selection = "test_neighbors_selection"
  497. self.to_remove.append(selection)
  498. self.runModule(
  499. "r.mapcalc",
  500. expression="{}=if(y()==15,1,null())".format(selection),
  501. )
  502. self.assertModule(
  503. "r.neighbors",
  504. input="elevation",
  505. output=",".join(outputs),
  506. selection=selection,
  507. method=list(self.test_options[test_case].keys()),
  508. )
  509. self.check_univar(test_case)
  510. def test_weighting_function(self):
  511. """Test results with gaussian weighting (standard options otherwise)."""
  512. test_case = "test_weighting_function"
  513. outputs = [
  514. "{}_raster_{}".format(test_case, method)
  515. for method in self.test_options[test_case]
  516. ]
  517. self.to_remove.extend(outputs)
  518. self.assertModule(
  519. "r.neighbors",
  520. input="elevation",
  521. size=7,
  522. weighting_function="gaussian",
  523. weighting_factor=2.0,
  524. output=",".join(outputs),
  525. method=list(self.test_options[test_case].keys()),
  526. )
  527. self.check_univar(test_case)
  528. def test_weighting_file(self):
  529. """Test results with file for weighting (standard options otherwise)."""
  530. test_case = "test_weighting_file"
  531. outputs = [
  532. "{}_raster_{}".format(test_case, method)
  533. for method in self.test_options[test_case]
  534. ]
  535. self.to_remove.extend(outputs)
  536. weights = tempfile()
  537. with open(weights, "w") as w:
  538. w.write("0 1 1 1 0\n1 0 0 0 1\n1 0 0 0 1\n1 0 0 0 1\n0 1 1 1 0")
  539. self.assertModule(
  540. "r.neighbors",
  541. input="elevation",
  542. size=5,
  543. weighting_function="file",
  544. output=",".join(outputs),
  545. method=list(self.test_options[test_case].keys()),
  546. weight=weights,
  547. )
  548. self.check_univar(test_case)
  549. # Module fails with mutual exclusive options
  550. self.assertModuleFail(
  551. "r.neighbors",
  552. input="elevation",
  553. flags="c",
  554. size=5,
  555. weighting_function="file",
  556. output="{}_fails".format(test_case),
  557. method="sum",
  558. weight=weights,
  559. )
  560. def test_standard_options_datatype(self):
  561. """Test if result is of integer or float data type depending on
  562. input datatype and method"""
  563. # landclass96 (values 1-7)
  564. test_case = "test_standard_options_datatype"
  565. methods = ["average", "variance", "diversity", "range", "mode"]
  566. outputs = ["{}_{}".format(test_case, method) for method in methods]
  567. self.to_remove.extend(outputs)
  568. self.assertModule(
  569. "r.neighbors",
  570. input="landclass96",
  571. output=",".join(outputs),
  572. method=methods,
  573. )
  574. for rmap in outputs:
  575. rinfo = raster_info(rmap)
  576. self.assertTrue(
  577. rinfo["datatype"] == "CELL"
  578. if rinfo["datatype"] in ["diversity", "range", "mode"]
  579. else "DCELL"
  580. )
  581. if __name__ == "__main__":
  582. test()