test_imagery_sigfile.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. """Test of imagery library signature file handling
  2. @author Maris Nartiss
  3. @copyright 2021 by Maris Nartiss and the GRASS Development Team
  4. @license This program is free software under the GNU General Public License (>=v2).
  5. Read the file COPYING that comes with GRASS
  6. for details
  7. """
  8. import os
  9. import stat
  10. import ctypes
  11. import shutil
  12. from grass.gunittest.case import TestCase
  13. from grass.gunittest.main import test
  14. from grass.script.core import tempname
  15. from grass.pygrass import utils
  16. from grass.pygrass.gis import Mapset
  17. from grass.lib.gis import G_mapset_path
  18. from grass.lib.raster import Rast_write_semantic_label
  19. from grass.lib.imagery import (
  20. Signature,
  21. Ref,
  22. I_init_signatures,
  23. I_new_signature,
  24. I_fopen_signature_file_new,
  25. I_write_signatures,
  26. I_fopen_signature_file_old,
  27. I_read_signatures,
  28. I_sort_signatures_by_semantic_label,
  29. I_free_signatures,
  30. I_init_group_ref,
  31. I_add_file_to_group_ref,
  32. I_free_group_ref,
  33. )
  34. class SignatureFileTestCase(TestCase):
  35. @classmethod
  36. def setUpClass(cls):
  37. cls.libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("c"))
  38. cls.mpath = utils.decode(G_mapset_path())
  39. cls.mapset_name = Mapset().name
  40. cls.sig_name = tempname(10)
  41. cls.sig_dir = f"{cls.mpath}/signatures/sig/{cls.sig_name}"
  42. @classmethod
  43. def tearDownClass(cls):
  44. shutil.rmtree(cls.sig_dir, ignore_errors=True)
  45. def test_I_fopen_signature_file_old_fail(self):
  46. sigfile = I_fopen_signature_file_old(tempname(10))
  47. self.assertFalse(sigfile)
  48. def test_roundtrip_signature_v1_norgb_one_label(self):
  49. """Test writing and reading back signature file (v1)
  50. wiht a single label"""
  51. # Create signature struct
  52. So = Signature()
  53. I_init_signatures(ctypes.byref(So), 1)
  54. self.assertEqual(So.nbands, 1)
  55. sig_count = I_new_signature(ctypes.byref(So))
  56. self.assertEqual(sig_count, 1)
  57. # Fill signatures struct with data
  58. So.title = b"Signature title"
  59. So.semantic_labels[0] = ctypes.create_string_buffer(b"The_Doors")
  60. So.sig[0].status = 1
  61. So.sig[0].have_color = 0
  62. So.sig[0].npoints = 42
  63. So.sig[0].desc = b"my label"
  64. So.sig[0].mean[0] = 2.5
  65. So.sig[0].var[0][0] = 0.7
  66. # Write signatures to file
  67. p_new_sigfile = I_fopen_signature_file_new(self.sig_name)
  68. sig_stat = os.stat(f"{self.sig_dir}/sig")
  69. self.assertTrue(stat.S_ISREG(sig_stat.st_mode))
  70. I_write_signatures(p_new_sigfile, ctypes.byref(So))
  71. self.libc.fclose(p_new_sigfile)
  72. # Read back from signatures file
  73. Sn = Signature()
  74. fq_name = f"{self.sig_name}@{self.mapset_name}"
  75. p_old_sigfile = I_fopen_signature_file_old(fq_name)
  76. ret = I_read_signatures(p_old_sigfile, ctypes.byref(Sn))
  77. self.assertEqual(ret, 1)
  78. self.assertEqual(Sn.title, b"Signature title")
  79. self.assertEqual(Sn.nbands, 1)
  80. semantic_label = utils.decode(
  81. ctypes.cast(Sn.semantic_labels[0], ctypes.c_char_p).value
  82. )
  83. self.assertEqual(semantic_label, "The_Doors")
  84. self.assertEqual(Sn.sig[0].status, 1)
  85. self.assertEqual(Sn.sig[0].have_color, 0)
  86. self.assertEqual(Sn.sig[0].npoints, 42)
  87. self.assertEqual(Sn.sig[0].desc, b"my label")
  88. self.assertEqual(Sn.sig[0].mean[0], 2.5)
  89. self.assertEqual(Sn.sig[0].var[0][0], 0.7)
  90. # Free signature struct after use
  91. So.semantic_labels[0] = None
  92. I_free_signatures(ctypes.byref(So))
  93. I_free_signatures(ctypes.byref(Sn))
  94. self.assertEqual(Sn.nbands, 0)
  95. self.assertEqual(Sn.nsigs, 0)
  96. def test_broken_signature_v1_norgb(self):
  97. """Test reading back signature file (v1) should fail due to
  98. single semantic label exceeding maximum length"""
  99. # Create signature struct
  100. So = Signature()
  101. I_init_signatures(ctypes.byref(So), 1)
  102. self.assertEqual(So.nbands, 1)
  103. sig_count = I_new_signature(ctypes.byref(So))
  104. self.assertEqual(sig_count, 1)
  105. # Fill signatures struct with data
  106. So.title = b"Signature title"
  107. # len(tempname(251)) == 255
  108. So.semantic_labels[0] = ctypes.create_string_buffer(tempname(251).encode())
  109. So.sig[0].status = 1
  110. So.sig[0].have_color = 0
  111. So.sig[0].npoints = 42
  112. So.sig[0].desc = b"my label"
  113. So.sig[0].mean[0] = 2.5
  114. So.sig[0].var[0][0] = 0.7
  115. # Write signatures to file
  116. p_new_sigfile = I_fopen_signature_file_new(self.sig_name)
  117. sig_stat = os.stat(f"{self.sig_dir}/sig")
  118. self.assertTrue(stat.S_ISREG(sig_stat.st_mode))
  119. I_write_signatures(p_new_sigfile, ctypes.byref(So))
  120. self.libc.fclose(p_new_sigfile)
  121. # Read back from signatures file
  122. Sn = Signature()
  123. p_old_sigfile = I_fopen_signature_file_old(self.sig_name)
  124. ret = I_read_signatures(p_old_sigfile, ctypes.byref(Sn))
  125. self.assertEqual(ret, -1)
  126. So.semantic_labels[0] = None
  127. I_free_signatures(ctypes.byref(So))
  128. I_free_signatures(ctypes.byref(Sn))
  129. def test_roundtrip_signature_v1_norgb_two_labelss(self):
  130. """Test writing and reading back signature (v1) with two labels"""
  131. # Create signature struct
  132. So = Signature()
  133. I_init_signatures(ctypes.byref(So), 2)
  134. self.assertEqual(So.nbands, 2)
  135. sig_count = I_new_signature(ctypes.byref(So))
  136. self.assertEqual(sig_count, 1)
  137. sig_count = I_new_signature(ctypes.byref(So))
  138. self.assertEqual(sig_count, 2)
  139. # Fill signatures struct with data
  140. So.title = b"Signature title"
  141. So.semantic_labels[0] = ctypes.create_string_buffer(b"The_Doors")
  142. So.semantic_labels[1] = ctypes.create_string_buffer(b"The_Who")
  143. So.sig[0].status = 1
  144. So.sig[0].have_color = 0
  145. So.sig[0].npoints = 42
  146. So.sig[0].desc = b"my label1"
  147. So.sig[0].mean[0] = 2.5
  148. So.sig[0].mean[1] = 3.5
  149. So.sig[0].var[0][0] = 0.7
  150. So.sig[0].var[1][0] = 0.2
  151. So.sig[0].var[1][1] = 0.8
  152. So.sig[1].status = 1
  153. So.sig[1].have_color = 0
  154. So.sig[1].npoints = 69
  155. So.sig[1].desc = b"my label2"
  156. So.sig[1].mean[0] = 3.5
  157. So.sig[1].mean[1] = 4.5
  158. So.sig[1].var[0][0] = 1.7
  159. So.sig[1].var[1][0] = 1.2
  160. So.sig[1].var[1][1] = 1.8
  161. # Write signatures to file
  162. p_new_sigfile = I_fopen_signature_file_new(self.sig_name)
  163. sig_stat = os.stat(f"{self.sig_dir}/sig")
  164. self.assertTrue(stat.S_ISREG(sig_stat.st_mode))
  165. I_write_signatures(p_new_sigfile, ctypes.byref(So))
  166. self.libc.fclose(p_new_sigfile)
  167. # Read back from signatures file
  168. Sn = Signature()
  169. p_old_sigfile = I_fopen_signature_file_old(self.sig_name)
  170. ret = I_read_signatures(p_old_sigfile, ctypes.byref(Sn))
  171. self.assertEqual(ret, 1)
  172. self.assertEqual(Sn.title, b"Signature title")
  173. self.assertEqual(Sn.nbands, 2)
  174. semantic_label = utils.decode(
  175. ctypes.cast(Sn.semantic_labels[0], ctypes.c_char_p).value
  176. )
  177. self.assertEqual(semantic_label, "The_Doors")
  178. self.assertEqual(Sn.sig[0].status, 1)
  179. self.assertEqual(Sn.sig[0].have_color, 0)
  180. self.assertEqual(Sn.sig[0].npoints, 42)
  181. self.assertEqual(Sn.sig[0].desc, b"my label1")
  182. self.assertEqual(Sn.sig[0].mean[0], 2.5)
  183. self.assertEqual(Sn.sig[0].mean[1], 3.5)
  184. self.assertEqual(Sn.sig[0].var[0][0], 0.7)
  185. self.assertEqual(Sn.sig[0].var[1][0], 0.2)
  186. self.assertEqual(Sn.sig[0].var[1][1], 0.8)
  187. semantic_label = utils.decode(
  188. ctypes.cast(Sn.semantic_labels[1], ctypes.c_char_p).value
  189. )
  190. self.assertEqual(semantic_label, "The_Who")
  191. self.assertEqual(Sn.sig[1].status, 1)
  192. self.assertEqual(Sn.sig[1].have_color, 0)
  193. self.assertEqual(Sn.sig[1].npoints, 69)
  194. self.assertEqual(Sn.sig[1].desc, b"my label2")
  195. self.assertEqual(Sn.sig[1].mean[0], 3.5)
  196. self.assertEqual(Sn.sig[1].mean[1], 4.5)
  197. self.assertEqual(Sn.sig[1].var[0][0], 1.7)
  198. self.assertEqual(Sn.sig[1].var[1][0], 1.2)
  199. self.assertEqual(Sn.sig[1].var[1][1], 1.8)
  200. # Free signature struct after use
  201. So.semantic_labels[0] = None
  202. So.semantic_labels[1] = None
  203. I_free_signatures(ctypes.byref(So))
  204. I_free_signatures(ctypes.byref(Sn))
  205. self.assertEqual(Sn.nbands, 0)
  206. self.assertEqual(Sn.nsigs, 0)
  207. class SortSignaturesBysemantic_labelTest(TestCase):
  208. @classmethod
  209. def setUpClass(cls):
  210. cls.libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("c"))
  211. cls.mapset = Mapset().name
  212. cls.map1 = tempname(10)
  213. cls.semantic_label1 = "The_Doors"
  214. cls.map2 = tempname(10)
  215. cls.semantic_label2 = "The_Who"
  216. cls.map3 = tempname(10)
  217. cls.use_temp_region()
  218. cls.runModule("g.region", n=1, s=0, e=1, w=0, res=1)
  219. cls.runModule("r.mapcalc", expression=f"{cls.map1} = 1")
  220. cls.runModule("r.mapcalc", expression=f"{cls.map2} = 1")
  221. cls.runModule("r.mapcalc", expression=f"{cls.map3} = 1")
  222. Rast_write_semantic_label(cls.map1, cls.semantic_label1)
  223. Rast_write_semantic_label(cls.map2, cls.semantic_label2)
  224. @classmethod
  225. def tearDownClass(cls):
  226. cls.del_temp_region()
  227. cls.runModule("g.remove", flags="f", type="raster", name=cls.map1)
  228. cls.runModule("g.remove", flags="f", type="raster", name=cls.map2)
  229. cls.runModule("g.remove", flags="f", type="raster", name=cls.map3)
  230. def test_symmetric_complete_difference(self):
  231. # Prepare imagery group reference struct
  232. R = Ref()
  233. I_init_group_ref(ctypes.byref(R))
  234. ret = I_add_file_to_group_ref(self.map1, self.mapset, ctypes.byref(R))
  235. self.assertEqual(ret, 0)
  236. # Prepare signature struct
  237. S = Signature()
  238. I_init_signatures(ctypes.byref(S), 1)
  239. self.assertEqual(S.nbands, 1)
  240. sig_count = I_new_signature(ctypes.byref(S))
  241. self.assertEqual(sig_count, 1)
  242. S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Troggs")
  243. S.title = b"Signature title"
  244. S.sig[0].status = 1
  245. S.sig[0].have_color = 0
  246. S.sig[0].npoints = 42
  247. S.sig[0].desc = b"my label"
  248. S.sig[0].mean[0] = 2.5
  249. S.sig[0].var[0][0] = 0.7
  250. # This should result in two error strings in ret
  251. ret = I_sort_signatures_by_semantic_label(ctypes.byref(S), ctypes.byref(R))
  252. self.assertTrue(bool(ret))
  253. sig_err = utils.decode(ctypes.cast(ret[0], ctypes.c_char_p).value)
  254. ref_err = utils.decode(ctypes.cast(ret[1], ctypes.c_char_p).value)
  255. self.assertEqual(sig_err, "The_Troggs")
  256. self.assertEqual(ref_err, "The_Doors")
  257. # Clean up memory to help track memory leaks when run by valgrind
  258. S.semantic_labels[
  259. 0
  260. ] = None # C should not call free() on memory allocated by python
  261. I_free_signatures(ctypes.byref(S))
  262. I_free_group_ref(ctypes.byref(R))
  263. if ret:
  264. if ret[0]:
  265. self.libc.free(ret[0])
  266. if ret[1]:
  267. self.libc.free(ret[1])
  268. self.libc.free(ret)
  269. def test_asymmetric_complete_difference(self):
  270. # Prepare imagery group reference struct
  271. R = Ref()
  272. I_init_group_ref(ctypes.byref(R))
  273. ret = I_add_file_to_group_ref(self.map1, self.mapset, ctypes.byref(R))
  274. self.assertEqual(ret, 0)
  275. ret = I_add_file_to_group_ref(self.map2, self.mapset, ctypes.byref(R))
  276. self.assertEqual(ret, 1)
  277. # Prepare signature struct
  278. S = Signature()
  279. I_init_signatures(ctypes.byref(S), 1)
  280. self.assertEqual(S.nbands, 1)
  281. sig_count = I_new_signature(ctypes.byref(S))
  282. self.assertEqual(sig_count, 1)
  283. S.title = b"Signature title"
  284. S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Troggs")
  285. S.sig[0].status = 1
  286. S.sig[0].have_color = 0
  287. S.sig[0].npoints = 42
  288. S.sig[0].desc = b"my label"
  289. S.sig[0].mean[0] = 2.5
  290. S.sig[0].var[0][0] = 0.7
  291. # This should result in two error strings in ret
  292. ret = I_sort_signatures_by_semantic_label(ctypes.byref(S), ctypes.byref(R))
  293. self.assertTrue(bool(ret))
  294. sig_err = utils.decode(ctypes.cast(ret[0], ctypes.c_char_p).value)
  295. ref_err = utils.decode(ctypes.cast(ret[1], ctypes.c_char_p).value)
  296. self.assertEqual(sig_err, "The_Troggs")
  297. self.assertEqual(ref_err, "The_Doors,The_Who")
  298. # Clean up memory to help track memory leaks when run by valgrind
  299. S.semantic_labels[0] = None
  300. I_free_signatures(ctypes.byref(S))
  301. I_free_group_ref(ctypes.byref(R))
  302. if ret:
  303. if ret[0]:
  304. self.libc.free(ret[0])
  305. if ret[1]:
  306. self.libc.free(ret[1])
  307. self.libc.free(ret)
  308. def test_missing_semantic_label(self):
  309. # Prepare imagery group reference struct
  310. R = Ref()
  311. I_init_group_ref(ctypes.byref(R))
  312. ret = I_add_file_to_group_ref(self.map1, self.mapset, ctypes.byref(R))
  313. self.assertEqual(ret, 0)
  314. ret = I_add_file_to_group_ref(self.map2, self.mapset, ctypes.byref(R))
  315. self.assertEqual(ret, 1)
  316. ret = I_add_file_to_group_ref(self.map3, self.mapset, ctypes.byref(R))
  317. self.assertEqual(ret, 2)
  318. # Prepare signature struct
  319. S = Signature()
  320. I_init_signatures(ctypes.byref(S), 10)
  321. self.assertEqual(S.nbands, 10)
  322. sig_count = I_new_signature(ctypes.byref(S))
  323. self.assertEqual(sig_count, 1)
  324. S.title = b"Signature title"
  325. S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Who")
  326. S.sig[0].status = 1
  327. S.sig[0].have_color = 0
  328. S.sig[0].npoints = 42
  329. S.sig[0].desc = b"my label"
  330. S.sig[0].mean[0] = 2.5
  331. S.sig[0].var[0][0] = 0.7
  332. # This should result in two error strings in ret
  333. ret = I_sort_signatures_by_semantic_label(ctypes.byref(S), ctypes.byref(R))
  334. self.assertTrue(bool(ret))
  335. sig_err = utils.decode(ctypes.cast(ret[0], ctypes.c_char_p).value)
  336. ref_err = utils.decode(ctypes.cast(ret[1], ctypes.c_char_p).value)
  337. self.assertEqual(
  338. sig_err,
  339. "<semantic label missing>,<semantic label missing>,"
  340. + "<semantic label missing>,<semantic label missing>,"
  341. + "<semantic label missing>,<semantic label missing>,"
  342. + "<semantic label missing>,<semantic label missing>,"
  343. + "<semantic label missing>",
  344. )
  345. self.assertEqual(ref_err, f"The_Doors,{self.map3}")
  346. # Clean up memory to help track memory leaks when run by valgrind
  347. S.semantic_labels[0] = None
  348. I_free_signatures(ctypes.byref(S))
  349. I_free_group_ref(ctypes.byref(R))
  350. if ret:
  351. if ret[0]:
  352. self.libc.free(ret[0])
  353. if ret[1]:
  354. self.libc.free(ret[1])
  355. self.libc.free(ret)
  356. def test_single_complete_match(self):
  357. # Prepare imagery group reference struct
  358. R = Ref()
  359. I_init_group_ref(ctypes.byref(R))
  360. ret = I_add_file_to_group_ref(self.map1, self.mapset, ctypes.byref(R))
  361. self.assertEqual(ret, 0)
  362. # Prepare signature struct
  363. S = Signature()
  364. I_init_signatures(ctypes.byref(S), 1)
  365. self.assertEqual(S.nbands, 1)
  366. sig_count = I_new_signature(ctypes.byref(S))
  367. self.assertEqual(sig_count, 1)
  368. S.title = b"Signature title"
  369. S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Doors")
  370. S.sig[0].status = 1
  371. S.sig[0].have_color = 0
  372. S.sig[0].npoints = 42
  373. S.sig[0].desc = b"my label"
  374. S.sig[0].mean[0] = 2.5
  375. S.sig[0].var[0][0] = 0.7
  376. # This should result in returning NULL
  377. ret = I_sort_signatures_by_semantic_label(ctypes.byref(S), ctypes.byref(R))
  378. self.assertFalse(bool(ret))
  379. semantic_label = utils.decode(
  380. ctypes.cast(S.semantic_labels[0], ctypes.c_char_p).value
  381. )
  382. self.assertEqual(semantic_label, "The_Doors")
  383. self.assertEqual(S.sig[0].mean[0], 2.5)
  384. self.assertEqual(S.sig[0].var[0][0], 0.7)
  385. # Clean up memory to help track memory leaks when run by valgrind
  386. S.semantic_labels[0] = None
  387. I_free_signatures(ctypes.byref(S))
  388. I_free_group_ref(ctypes.byref(R))
  389. if ret:
  390. if ret[0]:
  391. self.libc.free(ret[0])
  392. if ret[1]:
  393. self.libc.free(ret[1])
  394. self.libc.free(ret)
  395. def test_double_complete_match_reorder(self):
  396. # Prepare imagery group reference struct
  397. R = Ref()
  398. I_init_group_ref(ctypes.byref(R))
  399. ret = I_add_file_to_group_ref(self.map1, self.mapset, ctypes.byref(R))
  400. self.assertEqual(ret, 0)
  401. ret = I_add_file_to_group_ref(self.map2, self.mapset, ctypes.byref(R))
  402. self.assertEqual(ret, 1)
  403. # Prepare signature struct
  404. S = Signature()
  405. I_init_signatures(ctypes.byref(S), 2)
  406. self.assertEqual(S.nbands, 2)
  407. sig_count = I_new_signature(ctypes.byref(S))
  408. self.assertEqual(sig_count, 1)
  409. sig_count = I_new_signature(ctypes.byref(S))
  410. self.assertEqual(sig_count, 2)
  411. S.title = b"Signature title"
  412. S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Who")
  413. S.semantic_labels[1] = ctypes.create_string_buffer(b"The_Doors")
  414. S.sig[0].status = 1
  415. S.sig[0].have_color = 0
  416. S.sig[0].npoints = 69
  417. S.sig[0].desc = b"my label2"
  418. S.sig[0].mean[0] = 3.3
  419. S.sig[0].mean[1] = 6.6
  420. S.sig[0].var[0][0] = 1.7
  421. S.sig[0].var[1][0] = 1.2
  422. S.sig[0].var[1][1] = 1.8
  423. S.sig[1].status = 1
  424. S.sig[1].have_color = 0
  425. S.sig[1].npoints = 42
  426. S.sig[1].desc = b"my label1"
  427. S.sig[1].mean[0] = 2.2
  428. S.sig[1].mean[1] = 4.4
  429. S.sig[1].var[0][0] = 0.7
  430. S.sig[1].var[1][0] = 0.2
  431. S.sig[1].var[1][1] = 0.8
  432. # This should result in returning NULL
  433. ret = I_sort_signatures_by_semantic_label(ctypes.byref(S), ctypes.byref(R))
  434. self.assertFalse(bool(ret))
  435. # semantic labels and sig items should be swapped
  436. # Static items
  437. self.assertEqual(S.sig[0].npoints, 69)
  438. self.assertEqual(S.sig[1].npoints, 42)
  439. # Reordered items
  440. semantic_label1 = utils.decode(
  441. ctypes.cast(S.semantic_labels[0], ctypes.c_char_p).value
  442. )
  443. self.assertEqual(semantic_label1, "The_Doors")
  444. semantic_label2 = utils.decode(
  445. ctypes.cast(S.semantic_labels[1], ctypes.c_char_p).value
  446. )
  447. self.assertEqual(semantic_label2, "The_Who")
  448. self.assertEqual(S.sig[0].mean[0], 6.6)
  449. self.assertEqual(S.sig[0].mean[1], 3.3)
  450. self.assertEqual(S.sig[0].var[0][0], 1.8)
  451. self.assertEqual(S.sig[0].var[1][0], 1.2)
  452. self.assertEqual(S.sig[0].var[1][1], 1.7)
  453. self.assertEqual(S.sig[1].mean[0], 4.4)
  454. self.assertEqual(S.sig[1].mean[1], 2.2)
  455. self.assertEqual(S.sig[1].var[0][0], 0.8)
  456. self.assertEqual(S.sig[1].var[1][0], 0.2)
  457. self.assertEqual(S.sig[1].var[1][1], 0.7)
  458. # Clean up memory to help track memory leaks when run by valgrind
  459. S.semantic_labels[0] = None
  460. S.semantic_labels[1] = None
  461. I_free_signatures(ctypes.byref(S))
  462. I_free_group_ref(ctypes.byref(R))
  463. if ret:
  464. if ret[0]:
  465. self.libc.free(ret[0])
  466. if ret[1]:
  467. self.libc.free(ret[1])
  468. self.libc.free(ret)
  469. def test_double_complete_match_same_order(self):
  470. # Prepare imagery group reference struct
  471. R = Ref()
  472. I_init_group_ref(ctypes.byref(R))
  473. ret = I_add_file_to_group_ref(self.map2, self.mapset, ctypes.byref(R))
  474. self.assertEqual(ret, 0)
  475. ret = I_add_file_to_group_ref(self.map1, self.mapset, ctypes.byref(R))
  476. self.assertEqual(ret, 1)
  477. # Prepare signature struct
  478. S = Signature()
  479. I_init_signatures(ctypes.byref(S), 2)
  480. self.assertEqual(S.nbands, 2)
  481. sig_count = I_new_signature(ctypes.byref(S))
  482. self.assertEqual(sig_count, 1)
  483. sig_count = I_new_signature(ctypes.byref(S))
  484. self.assertEqual(sig_count, 2)
  485. S.title = b"Signature title"
  486. S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Who")
  487. S.semantic_labels[1] = ctypes.create_string_buffer(b"The_Doors")
  488. S.sig[0].status = 1
  489. S.sig[0].have_color = 0
  490. S.sig[0].npoints = 69
  491. S.sig[0].desc = b"my label2"
  492. S.sig[0].mean[0] = 3.5
  493. S.sig[0].var[0][0] = 1.7
  494. S.sig[0].var[1][0] = 1.2
  495. S.sig[0].var[1][1] = 1.8
  496. S.sig[1].status = 1
  497. S.sig[1].have_color = 0
  498. S.sig[1].npoints = 42
  499. S.sig[1].desc = b"my label1"
  500. S.sig[1].mean[0] = 2.5
  501. S.sig[1].var[0][0] = 0.7
  502. S.sig[1].var[1][0] = 0.2
  503. S.sig[1].var[1][1] = 0.8
  504. # This should result in returning NULL
  505. ret = I_sort_signatures_by_semantic_label(ctypes.byref(S), ctypes.byref(R))
  506. self.assertFalse(bool(ret))
  507. # semantic labels and sig items should not be swapped
  508. # Static items
  509. self.assertEqual(S.sig[0].npoints, 69)
  510. self.assertEqual(S.sig[1].npoints, 42)
  511. # Reordered items
  512. semantic_label1 = utils.decode(
  513. ctypes.cast(S.semantic_labels[0], ctypes.c_char_p).value
  514. )
  515. self.assertEqual(semantic_label1, "The_Who")
  516. semantic_label2 = utils.decode(
  517. ctypes.cast(S.semantic_labels[1], ctypes.c_char_p).value
  518. )
  519. self.assertEqual(semantic_label2, "The_Doors")
  520. self.assertEqual(S.sig[0].mean[0], 3.5)
  521. self.assertEqual(S.sig[0].var[0][0], 1.7)
  522. self.assertEqual(S.sig[1].mean[0], 2.5)
  523. self.assertEqual(S.sig[1].var[0][0], 0.7)
  524. # Clean up memory to help track memory leaks when run by valgrind
  525. S.semantic_labels[0] = None
  526. S.semantic_labels[1] = None
  527. I_free_signatures(ctypes.byref(S))
  528. I_free_group_ref(ctypes.byref(R))
  529. if ret:
  530. if ret[0]:
  531. self.libc.free(ret[0])
  532. if ret[1]:
  533. self.libc.free(ret[1])
  534. self.libc.free(ret)
  535. def test_complete_match_reorder(self):
  536. # Prepare imagery group reference struct
  537. R = Ref()
  538. I_init_group_ref(ctypes.byref(R))
  539. ret = I_add_file_to_group_ref(self.map1, self.mapset, ctypes.byref(R))
  540. self.assertEqual(ret, 0)
  541. ret = I_add_file_to_group_ref(self.map2, self.mapset, ctypes.byref(R))
  542. self.assertEqual(ret, 1)
  543. # Prepare signature struct
  544. S = Signature()
  545. I_init_signatures(ctypes.byref(S), 2)
  546. self.assertEqual(S.nbands, 2)
  547. sig_count = I_new_signature(ctypes.byref(S))
  548. self.assertEqual(sig_count, 1)
  549. sig_count = I_new_signature(ctypes.byref(S))
  550. self.assertEqual(sig_count, 2)
  551. sig_count = I_new_signature(ctypes.byref(S))
  552. self.assertEqual(sig_count, 3)
  553. sig_count = I_new_signature(ctypes.byref(S))
  554. self.assertEqual(sig_count, 4)
  555. S.title = b"Signature title"
  556. S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Who")
  557. S.semantic_labels[1] = ctypes.create_string_buffer(b"The_Doors")
  558. S.sig[0].status = 1
  559. S.sig[0].have_color = 0
  560. S.sig[0].npoints = 69
  561. S.sig[0].desc = b"my label2"
  562. S.sig[0].mean[0] = 3.3
  563. S.sig[0].mean[1] = 6.6
  564. S.sig[0].var[0][0] = 1.7
  565. S.sig[0].var[1][0] = 1.2
  566. S.sig[0].var[1][1] = 1.8
  567. S.sig[1].status = 1
  568. S.sig[1].have_color = 0
  569. S.sig[1].npoints = 42
  570. S.sig[1].desc = b"my label1"
  571. S.sig[1].mean[0] = 2.2
  572. S.sig[1].mean[1] = 4.4
  573. S.sig[1].var[0][0] = 0.7
  574. S.sig[1].var[1][0] = 0.2
  575. S.sig[1].var[1][1] = 0.8
  576. S.sig[2].status = 1
  577. S.sig[2].have_color = 0
  578. S.sig[2].npoints = 12
  579. S.sig[2].desc = b"my label4"
  580. S.sig[2].mean[0] = 5.5
  581. S.sig[2].mean[1] = 9.9
  582. S.sig[2].var[0][0] = 0.9
  583. S.sig[2].var[1][0] = 0.8
  584. S.sig[2].var[1][1] = 0.7
  585. S.sig[3].status = 1
  586. S.sig[3].have_color = 0
  587. S.sig[3].npoints = 21
  588. S.sig[3].desc = b"my label3"
  589. S.sig[3].mean[0] = 9.9
  590. S.sig[3].mean[1] = 3.3
  591. S.sig[3].var[0][0] = 0.8
  592. S.sig[3].var[1][0] = 0.7
  593. S.sig[3].var[1][1] = 0.6
  594. # This should result in returning NULL
  595. ret = I_sort_signatures_by_semantic_label(ctypes.byref(S), ctypes.byref(R))
  596. self.assertFalse(bool(ret))
  597. # semantic labels and sig items should be swapped
  598. # Static items
  599. self.assertEqual(S.sig[0].npoints, 69)
  600. self.assertEqual(S.sig[1].npoints, 42)
  601. self.assertEqual(S.sig[2].npoints, 12)
  602. self.assertEqual(S.sig[3].npoints, 21)
  603. # Reordered items
  604. semantic_label1 = utils.decode(
  605. ctypes.cast(S.semantic_labels[0], ctypes.c_char_p).value
  606. )
  607. self.assertEqual(semantic_label1, "The_Doors")
  608. semantic_label2 = utils.decode(
  609. ctypes.cast(S.semantic_labels[1], ctypes.c_char_p).value
  610. )
  611. self.assertEqual(semantic_label2, "The_Who")
  612. self.assertEqual(S.sig[0].mean[0], 6.6)
  613. self.assertEqual(S.sig[0].mean[1], 3.3)
  614. self.assertEqual(S.sig[0].var[0][0], 1.8)
  615. self.assertEqual(S.sig[0].var[1][0], 1.2)
  616. self.assertEqual(S.sig[0].var[1][1], 1.7)
  617. self.assertEqual(S.sig[1].mean[0], 4.4)
  618. self.assertEqual(S.sig[1].mean[1], 2.2)
  619. self.assertEqual(S.sig[1].var[0][0], 0.8)
  620. self.assertEqual(S.sig[1].var[1][0], 0.2)
  621. self.assertEqual(S.sig[1].var[1][1], 0.7)
  622. self.assertEqual(S.sig[2].mean[0], 9.9)
  623. self.assertEqual(S.sig[2].mean[1], 5.5)
  624. self.assertEqual(S.sig[2].var[0][0], 0.7)
  625. self.assertEqual(S.sig[2].var[1][0], 0.8)
  626. self.assertEqual(S.sig[2].var[1][1], 0.9)
  627. self.assertEqual(S.sig[3].mean[0], 3.3)
  628. self.assertEqual(S.sig[3].mean[1], 9.9)
  629. self.assertEqual(S.sig[3].var[0][0], 0.6)
  630. self.assertEqual(S.sig[3].var[1][0], 0.7)
  631. self.assertEqual(S.sig[3].var[1][1], 0.8)
  632. # Clean up memory to help track memory leaks when run by valgrind
  633. S.semantic_labels[0] = None
  634. S.semantic_labels[1] = None
  635. I_free_signatures(ctypes.byref(S))
  636. I_free_group_ref(ctypes.byref(R))
  637. if ret:
  638. if ret[0]:
  639. self.libc.free(ret[0])
  640. if ret[1]:
  641. self.libc.free(ret[1])
  642. self.libc.free(ret)
  643. if __name__ == "__main__":
  644. test()