From 3076899a22f48c9cef7b8ef73a66cad73d34e5bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C4=81ris=20Narti=C5=A1s?= Date: Tue, 5 Oct 2021 21:24:54 +0300 Subject: [PATCH 01/11] Start the transition from band references to semantic labels --- lib/imagery/testsuite/test_imagery_sigfile.py | 174 ++++++++++-------- .../testsuite/test_imagery_sigsetfile.py | 122 ++++++------ lib/raster/raster_metadata.c | 62 +++---- lib/raster/testsuite/test_raster_metadata.py | 76 ++++---- 4 files changed, 236 insertions(+), 198 deletions(-) diff --git a/lib/imagery/testsuite/test_imagery_sigfile.py b/lib/imagery/testsuite/test_imagery_sigfile.py index e8815d80d27..9669882cec2 100644 --- a/lib/imagery/testsuite/test_imagery_sigfile.py +++ b/lib/imagery/testsuite/test_imagery_sigfile.py @@ -21,7 +21,7 @@ from grass.pygrass.gis import Mapset from grass.lib.gis import G_mapset_path -from grass.lib.raster import Rast_write_bandref +from grass.lib.raster import Rast_write_semantic_label from grass.lib.imagery import ( Signature, Ref, @@ -31,7 +31,7 @@ I_write_signatures, I_fopen_signature_file_old, I_read_signatures, - I_sort_signatures_by_bandref, + I_sort_signatures_by_semantic_label, I_free_signatures, I_init_group_ref, I_add_file_to_group_ref, @@ -56,9 +56,9 @@ def test_I_fopen_signature_file_old_fail(self): sigfile = I_fopen_signature_file_old(tempname(10)) self.assertFalse(sigfile) - def test_roundtrip_signature_v1_norgb_one_band(self): + def test_roundtrip_signature_v1_norgb_one_label(self): """Test writing and reading back signature file (v1) - wiht a single band""" + wiht a single label""" # Create signature struct So = Signature() @@ -69,7 +69,7 @@ def test_roundtrip_signature_v1_norgb_one_band(self): # Fill signatures struct with data So.title = b"Signature title" - So.bandrefs[0] = ctypes.create_string_buffer(b"The_Doors") + So.semantic_labels[0] = ctypes.create_string_buffer(b"The_Doors") So.sig[0].status = 1 So.sig[0].have_color = 0 So.sig[0].npoints = 42 @@ -92,8 +92,10 @@ def test_roundtrip_signature_v1_norgb_one_band(self): self.assertEqual(ret, 1) self.assertEqual(Sn.title, b"Signature title") self.assertEqual(Sn.nbands, 1) - bandref = utils.decode(ctypes.cast(Sn.bandrefs[0], ctypes.c_char_p).value) - self.assertEqual(bandref, "The_Doors") + semantic_label = utils.decode( + ctypes.cast(Sn.semantic_labels[0], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label, "The_Doors") self.assertEqual(Sn.sig[0].status, 1) self.assertEqual(Sn.sig[0].have_color, 0) self.assertEqual(Sn.sig[0].npoints, 42) @@ -102,7 +104,7 @@ def test_roundtrip_signature_v1_norgb_one_band(self): self.assertEqual(Sn.sig[0].var[0][0], 0.7) # Free signature struct after use - So.bandrefs[0] = None + So.semantic_labels[0] = None I_free_signatures(ctypes.byref(So)) I_free_signatures(ctypes.byref(Sn)) self.assertEqual(Sn.nbands, 0) @@ -110,7 +112,7 @@ def test_roundtrip_signature_v1_norgb_one_band(self): def test_broken_signature_v1_norgb(self): """Test reading back signature file (v1) should fail due to - single band reference exceeding maximum length""" + single semantic label exceeding maximum length""" # Create signature struct So = Signature() @@ -122,7 +124,7 @@ def test_broken_signature_v1_norgb(self): # Fill signatures struct with data So.title = b"Signature title" # len(tempname(251)) == 255 - So.bandrefs[0] = ctypes.create_string_buffer(tempname(251).encode()) + So.semantic_labels[0] = ctypes.create_string_buffer(tempname(251).encode()) So.sig[0].status = 1 So.sig[0].have_color = 0 So.sig[0].npoints = 42 @@ -143,12 +145,12 @@ def test_broken_signature_v1_norgb(self): ret = I_read_signatures(p_old_sigfile, ctypes.byref(Sn)) self.assertEqual(ret, -1) - So.bandrefs[0] = None + So.semantic_labels[0] = None I_free_signatures(ctypes.byref(So)) I_free_signatures(ctypes.byref(Sn)) - def test_roundtrip_signature_v1_norgb_two_bands(self): - """Test writing and reading back signature (v1) with two bands""" + def test_roundtrip_signature_v1_norgb_two_labelss(self): + """Test writing and reading back signature (v1) with two labels""" # Create signature struct So = Signature() @@ -161,8 +163,8 @@ def test_roundtrip_signature_v1_norgb_two_bands(self): # Fill signatures struct with data So.title = b"Signature title" - So.bandrefs[0] = ctypes.create_string_buffer(b"The_Doors") - So.bandrefs[1] = ctypes.create_string_buffer(b"The_Who") + So.semantic_labels[0] = ctypes.create_string_buffer(b"The_Doors") + So.semantic_labels[1] = ctypes.create_string_buffer(b"The_Who") So.sig[0].status = 1 So.sig[0].have_color = 0 So.sig[0].npoints = 42 @@ -196,8 +198,10 @@ def test_roundtrip_signature_v1_norgb_two_bands(self): self.assertEqual(ret, 1) self.assertEqual(Sn.title, b"Signature title") self.assertEqual(Sn.nbands, 2) - bandref = utils.decode(ctypes.cast(Sn.bandrefs[0], ctypes.c_char_p).value) - self.assertEqual(bandref, "The_Doors") + semantic_label = utils.decode( + ctypes.cast(Sn.semantic_labels[0], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label, "The_Doors") self.assertEqual(Sn.sig[0].status, 1) self.assertEqual(Sn.sig[0].have_color, 0) self.assertEqual(Sn.sig[0].npoints, 42) @@ -207,8 +211,10 @@ def test_roundtrip_signature_v1_norgb_two_bands(self): self.assertEqual(Sn.sig[0].var[0][0], 0.7) self.assertEqual(Sn.sig[0].var[1][0], 0.2) self.assertEqual(Sn.sig[0].var[1][1], 0.8) - bandref = utils.decode(ctypes.cast(Sn.bandrefs[1], ctypes.c_char_p).value) - self.assertEqual(bandref, "The_Who") + semantic_label = utils.decode( + ctypes.cast(Sn.semantic_labels[1], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label, "The_Who") self.assertEqual(Sn.sig[1].status, 1) self.assertEqual(Sn.sig[1].have_color, 0) self.assertEqual(Sn.sig[1].npoints, 69) @@ -220,31 +226,31 @@ def test_roundtrip_signature_v1_norgb_two_bands(self): self.assertEqual(Sn.sig[1].var[1][1], 1.8) # Free signature struct after use - So.bandrefs[0] = None - So.bandrefs[1] = None + So.semantic_labels[0] = None + So.semantic_labels[1] = None I_free_signatures(ctypes.byref(So)) I_free_signatures(ctypes.byref(Sn)) self.assertEqual(Sn.nbands, 0) self.assertEqual(Sn.nsigs, 0) -class SortSignaturesByBandrefTest(TestCase): +class SortSignaturesBysemantic_labelTest(TestCase): @classmethod def setUpClass(cls): cls.libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("c")) cls.mapset = Mapset().name cls.map1 = tempname(10) - cls.bandref1 = "The_Doors" + cls.semantic_label1 = "The_Doors" cls.map2 = tempname(10) - cls.bandref2 = "The_Who" + cls.semantic_label2 = "The_Who" cls.map3 = tempname(10) cls.use_temp_region() cls.runModule("g.region", n=1, s=0, e=1, w=0, res=1) cls.runModule("r.mapcalc", expression=f"{cls.map1} = 1") cls.runModule("r.mapcalc", expression=f"{cls.map2} = 1") cls.runModule("r.mapcalc", expression=f"{cls.map3} = 1") - Rast_write_bandref(cls.map1, cls.bandref1) - Rast_write_bandref(cls.map2, cls.bandref2) + Rast_write_semantic_label(cls.map1, cls.semantic_label1) + Rast_write_semantic_label(cls.map2, cls.semantic_label2) @classmethod def tearDownClass(cls): @@ -266,7 +272,7 @@ def test_symmetric_complete_difference(self): self.assertEqual(S.nbands, 1) sig_count = I_new_signature(ctypes.byref(S)) self.assertEqual(sig_count, 1) - S.bandrefs[0] = ctypes.create_string_buffer(b"The_Troggs") + S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Troggs") S.title = b"Signature title" S.sig[0].status = 1 S.sig[0].have_color = 0 @@ -276,7 +282,7 @@ def test_symmetric_complete_difference(self): S.sig[0].var[0][0] = 0.7 # This should result in two error strings in ret - ret = I_sort_signatures_by_bandref(ctypes.byref(S), ctypes.byref(R)) + ret = I_sort_signatures_by_semantic_label(ctypes.byref(S), ctypes.byref(R)) self.assertTrue(bool(ret)) sig_err = utils.decode(ctypes.cast(ret[0], ctypes.c_char_p).value) ref_err = utils.decode(ctypes.cast(ret[1], ctypes.c_char_p).value) @@ -284,7 +290,9 @@ def test_symmetric_complete_difference(self): self.assertEqual(ref_err, "The_Doors") # Clean up memory to help track memory leaks when run by valgrind - S.bandrefs[0] = None # C should not call free() on memory allocated by python + S.semantic_labels[ + 0 + ] = None # C should not call free() on memory allocated by python I_free_signatures(ctypes.byref(S)) I_free_group_ref(ctypes.byref(R)) if ret: @@ -310,7 +318,7 @@ def test_asymmetric_complete_difference(self): sig_count = I_new_signature(ctypes.byref(S)) self.assertEqual(sig_count, 1) S.title = b"Signature title" - S.bandrefs[0] = ctypes.create_string_buffer(b"The_Troggs") + S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Troggs") S.sig[0].status = 1 S.sig[0].have_color = 0 S.sig[0].npoints = 42 @@ -319,7 +327,7 @@ def test_asymmetric_complete_difference(self): S.sig[0].var[0][0] = 0.7 # This should result in two error strings in ret - ret = I_sort_signatures_by_bandref(ctypes.byref(S), ctypes.byref(R)) + ret = I_sort_signatures_by_semantic_label(ctypes.byref(S), ctypes.byref(R)) self.assertTrue(bool(ret)) sig_err = utils.decode(ctypes.cast(ret[0], ctypes.c_char_p).value) ref_err = utils.decode(ctypes.cast(ret[1], ctypes.c_char_p).value) @@ -327,7 +335,7 @@ def test_asymmetric_complete_difference(self): self.assertEqual(ref_err, "The_Doors,The_Who") # Clean up memory to help track memory leaks when run by valgrind - S.bandrefs[0] = None + S.semantic_labels[0] = None I_free_signatures(ctypes.byref(S)) I_free_group_ref(ctypes.byref(R)) if ret: @@ -337,7 +345,7 @@ def test_asymmetric_complete_difference(self): self.libc.free(ret[1]) self.libc.free(ret) - def test_missing_bandref(self): + def test_missing_semantic_label(self): # Prepare imagery group reference struct R = Ref() I_init_group_ref(ctypes.byref(R)) @@ -355,7 +363,7 @@ def test_missing_bandref(self): sig_count = I_new_signature(ctypes.byref(S)) self.assertEqual(sig_count, 1) S.title = b"Signature title" - S.bandrefs[0] = ctypes.create_string_buffer(b"The_Who") + S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Who") S.sig[0].status = 1 S.sig[0].have_color = 0 S.sig[0].npoints = 42 @@ -364,22 +372,22 @@ def test_missing_bandref(self): S.sig[0].var[0][0] = 0.7 # This should result in two error strings in ret - ret = I_sort_signatures_by_bandref(ctypes.byref(S), ctypes.byref(R)) + ret = I_sort_signatures_by_semantic_label(ctypes.byref(S), ctypes.byref(R)) self.assertTrue(bool(ret)) sig_err = utils.decode(ctypes.cast(ret[0], ctypes.c_char_p).value) ref_err = utils.decode(ctypes.cast(ret[1], ctypes.c_char_p).value) self.assertEqual( sig_err, - ",," - + ",," - + ",," - + ",," - + "", + ",," + + ",," + + ",," + + ",," + + "", ) self.assertEqual(ref_err, f"The_Doors,{self.map3}") # Clean up memory to help track memory leaks when run by valgrind - S.bandrefs[0] = None + S.semantic_labels[0] = None I_free_signatures(ctypes.byref(S)) I_free_group_ref(ctypes.byref(R)) if ret: @@ -403,7 +411,7 @@ def test_single_complete_match(self): sig_count = I_new_signature(ctypes.byref(S)) self.assertEqual(sig_count, 1) S.title = b"Signature title" - S.bandrefs[0] = ctypes.create_string_buffer(b"The_Doors") + S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Doors") S.sig[0].status = 1 S.sig[0].have_color = 0 S.sig[0].npoints = 42 @@ -412,15 +420,17 @@ def test_single_complete_match(self): S.sig[0].var[0][0] = 0.7 # This should result in returning NULL - ret = I_sort_signatures_by_bandref(ctypes.byref(S), ctypes.byref(R)) + ret = I_sort_signatures_by_semantic_label(ctypes.byref(S), ctypes.byref(R)) self.assertFalse(bool(ret)) - bandref = utils.decode(ctypes.cast(S.bandrefs[0], ctypes.c_char_p).value) - self.assertEqual(bandref, "The_Doors") + semantic_label = utils.decode( + ctypes.cast(S.semantic_labels[0], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label, "The_Doors") self.assertEqual(S.sig[0].mean[0], 2.5) self.assertEqual(S.sig[0].var[0][0], 0.7) # Clean up memory to help track memory leaks when run by valgrind - S.bandrefs[0] = None + S.semantic_labels[0] = None I_free_signatures(ctypes.byref(S)) I_free_group_ref(ctypes.byref(R)) if ret: @@ -448,8 +458,8 @@ def test_double_complete_match_reorder(self): sig_count = I_new_signature(ctypes.byref(S)) self.assertEqual(sig_count, 2) S.title = b"Signature title" - S.bandrefs[0] = ctypes.create_string_buffer(b"The_Who") - S.bandrefs[1] = ctypes.create_string_buffer(b"The_Doors") + S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Who") + S.semantic_labels[1] = ctypes.create_string_buffer(b"The_Doors") S.sig[0].status = 1 S.sig[0].have_color = 0 S.sig[0].npoints = 69 @@ -470,17 +480,21 @@ def test_double_complete_match_reorder(self): S.sig[1].var[1][1] = 0.8 # This should result in returning NULL - ret = I_sort_signatures_by_bandref(ctypes.byref(S), ctypes.byref(R)) + ret = I_sort_signatures_by_semantic_label(ctypes.byref(S), ctypes.byref(R)) self.assertFalse(bool(ret)) - # Band references and sig items should be swapped + # semantic labels and sig items should be swapped # Static items self.assertEqual(S.sig[0].npoints, 69) self.assertEqual(S.sig[1].npoints, 42) # Reordered items - bandref1 = utils.decode(ctypes.cast(S.bandrefs[0], ctypes.c_char_p).value) - self.assertEqual(bandref1, "The_Doors") - bandref2 = utils.decode(ctypes.cast(S.bandrefs[1], ctypes.c_char_p).value) - self.assertEqual(bandref2, "The_Who") + semantic_label1 = utils.decode( + ctypes.cast(S.semantic_labels[0], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label1, "The_Doors") + semantic_label2 = utils.decode( + ctypes.cast(S.semantic_labels[1], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label2, "The_Who") self.assertEqual(S.sig[0].mean[0], 6.6) self.assertEqual(S.sig[0].mean[1], 3.3) self.assertEqual(S.sig[0].var[0][0], 1.8) @@ -493,8 +507,8 @@ def test_double_complete_match_reorder(self): self.assertEqual(S.sig[1].var[1][1], 0.7) # Clean up memory to help track memory leaks when run by valgrind - S.bandrefs[0] = None - S.bandrefs[1] = None + S.semantic_labels[0] = None + S.semantic_labels[1] = None I_free_signatures(ctypes.byref(S)) I_free_group_ref(ctypes.byref(R)) if ret: @@ -522,8 +536,8 @@ def test_double_complete_match_same_order(self): sig_count = I_new_signature(ctypes.byref(S)) self.assertEqual(sig_count, 2) S.title = b"Signature title" - S.bandrefs[0] = ctypes.create_string_buffer(b"The_Who") - S.bandrefs[1] = ctypes.create_string_buffer(b"The_Doors") + S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Who") + S.semantic_labels[1] = ctypes.create_string_buffer(b"The_Doors") S.sig[0].status = 1 S.sig[0].have_color = 0 S.sig[0].npoints = 69 @@ -542,25 +556,29 @@ def test_double_complete_match_same_order(self): S.sig[1].var[1][1] = 0.8 # This should result in returning NULL - ret = I_sort_signatures_by_bandref(ctypes.byref(S), ctypes.byref(R)) + ret = I_sort_signatures_by_semantic_label(ctypes.byref(S), ctypes.byref(R)) self.assertFalse(bool(ret)) - # Band references and sig items should not be swapped + # semantic labels and sig items should not be swapped # Static items self.assertEqual(S.sig[0].npoints, 69) self.assertEqual(S.sig[1].npoints, 42) # Reordered items - bandref1 = utils.decode(ctypes.cast(S.bandrefs[0], ctypes.c_char_p).value) - self.assertEqual(bandref1, "The_Who") - bandref2 = utils.decode(ctypes.cast(S.bandrefs[1], ctypes.c_char_p).value) - self.assertEqual(bandref2, "The_Doors") + semantic_label1 = utils.decode( + ctypes.cast(S.semantic_labels[0], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label1, "The_Who") + semantic_label2 = utils.decode( + ctypes.cast(S.semantic_labels[1], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label2, "The_Doors") self.assertEqual(S.sig[0].mean[0], 3.5) self.assertEqual(S.sig[0].var[0][0], 1.7) self.assertEqual(S.sig[1].mean[0], 2.5) self.assertEqual(S.sig[1].var[0][0], 0.7) # Clean up memory to help track memory leaks when run by valgrind - S.bandrefs[0] = None - S.bandrefs[1] = None + S.semantic_labels[0] = None + S.semantic_labels[1] = None I_free_signatures(ctypes.byref(S)) I_free_group_ref(ctypes.byref(R)) if ret: @@ -592,8 +610,8 @@ def test_complete_match_reorder(self): sig_count = I_new_signature(ctypes.byref(S)) self.assertEqual(sig_count, 4) S.title = b"Signature title" - S.bandrefs[0] = ctypes.create_string_buffer(b"The_Who") - S.bandrefs[1] = ctypes.create_string_buffer(b"The_Doors") + S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Who") + S.semantic_labels[1] = ctypes.create_string_buffer(b"The_Doors") S.sig[0].status = 1 S.sig[0].have_color = 0 S.sig[0].npoints = 69 @@ -632,19 +650,23 @@ def test_complete_match_reorder(self): S.sig[3].var[1][1] = 0.6 # This should result in returning NULL - ret = I_sort_signatures_by_bandref(ctypes.byref(S), ctypes.byref(R)) + ret = I_sort_signatures_by_semantic_label(ctypes.byref(S), ctypes.byref(R)) self.assertFalse(bool(ret)) - # Band references and sig items should be swapped + # semantic labels and sig items should be swapped # Static items self.assertEqual(S.sig[0].npoints, 69) self.assertEqual(S.sig[1].npoints, 42) self.assertEqual(S.sig[2].npoints, 12) self.assertEqual(S.sig[3].npoints, 21) # Reordered items - bandref1 = utils.decode(ctypes.cast(S.bandrefs[0], ctypes.c_char_p).value) - self.assertEqual(bandref1, "The_Doors") - bandref2 = utils.decode(ctypes.cast(S.bandrefs[1], ctypes.c_char_p).value) - self.assertEqual(bandref2, "The_Who") + semantic_label1 = utils.decode( + ctypes.cast(S.semantic_labels[0], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label1, "The_Doors") + semantic_label2 = utils.decode( + ctypes.cast(S.semantic_labels[1], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label2, "The_Who") self.assertEqual(S.sig[0].mean[0], 6.6) self.assertEqual(S.sig[0].mean[1], 3.3) self.assertEqual(S.sig[0].var[0][0], 1.8) @@ -667,8 +689,8 @@ def test_complete_match_reorder(self): self.assertEqual(S.sig[3].var[1][1], 0.8) # Clean up memory to help track memory leaks when run by valgrind - S.bandrefs[0] = None - S.bandrefs[1] = None + S.semantic_labels[0] = None + S.semantic_labels[1] = None I_free_signatures(ctypes.byref(S)) I_free_group_ref(ctypes.byref(R)) if ret: diff --git a/lib/imagery/testsuite/test_imagery_sigsetfile.py b/lib/imagery/testsuite/test_imagery_sigsetfile.py index 27e575ada1b..14e85ea930b 100644 --- a/lib/imagery/testsuite/test_imagery_sigsetfile.py +++ b/lib/imagery/testsuite/test_imagery_sigsetfile.py @@ -21,7 +21,7 @@ from grass.pygrass.gis import Mapset from grass.lib.gis import G_mapset_path -from grass.lib.raster import Rast_write_bandref +from grass.lib.raster import Rast_write_semantic_label from grass.lib.imagery import ( SigSet, I_InitSigSet, @@ -29,7 +29,7 @@ I_NewSubSig, I_WriteSigSet, I_ReadSigSet, - I_SortSigSetByBandref, + I_SortSigSetBySemanticLabel, I_fopen_sigset_file_new, I_fopen_sigset_file_old, Ref, @@ -57,9 +57,9 @@ def test_I_fopen_signature_file_old_fail(self): sigfile = I_fopen_sigset_file_old(tempname(10)) self.assertFalse(sigfile) - def test_roundtrip_sigset_v1_one_band(self): + def test_roundtrip_sigset_v1_one_label(self): """Test writing and reading back sigset file (v1) - with a single band and fully qualified sigfile name""" + with a single label and fully qualified sigfile name""" # Create signature struct So = SigSet() @@ -72,7 +72,7 @@ def test_roundtrip_sigset_v1_one_band(self): # Fill sigset struct with data So.title = ReturnString("Signature title") - So.bandrefs[0] = ctypes.create_string_buffer(b"The_Doors") + So.semantic_labels[0] = ctypes.create_string_buffer(b"The_Doors") So.ClassSig[0].used = 1 So.ClassSig[0].classnum = 2 So.ClassSig[0].title = ReturnString("1st class") @@ -96,8 +96,10 @@ def test_roundtrip_sigset_v1_one_band(self): self.assertEqual(ret, 1) self.assertEqual(utils.decode(Sn.title), "Signature title") self.assertEqual(Sn.nbands, 1) - bandref = utils.decode(ctypes.cast(Sn.bandrefs[0], ctypes.c_char_p).value) - self.assertEqual(bandref, "The_Doors") + semantic_label = utils.decode( + ctypes.cast(Sn.semantic_label[0], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label, "The_Doors") self.assertEqual(Sn.nclasses, 1) self.assertEqual(Sn.ClassSig[0].nsubclasses, 1) self.assertEqual(Sn.ClassSig[0].used, 1) @@ -111,8 +113,8 @@ def test_roundtrip_sigset_v1_one_band(self): # SigSet does not have free function - def test_read_fail_sigset_v1_one_band(self): - """Reading back should fail as band reference exceeds limit""" + def test_read_fail_sigset_v1_one_label(self): + """Reading back should fail as semantic label length exceeds limit""" # Create signature struct So = SigSet() @@ -125,7 +127,7 @@ def test_read_fail_sigset_v1_one_band(self): # Fill sigset struct with data So.title = ReturnString("Signature title") - So.bandrefs[0] = ctypes.create_string_buffer(tempname(252).encode()) + So.semantic_labels[0] = ctypes.create_string_buffer(tempname(252).encode()) So.ClassSig[0].used = 1 So.ClassSig[0].classnum = 2 So.ClassSig[0].title = ReturnString("1st class") @@ -150,8 +152,8 @@ def test_read_fail_sigset_v1_one_band(self): # SigSet does not have free function - def test_roundtrip_sigset_v1_two_bands(self): - """Test writing and reading back sigset (v1) with two bands""" + def test_roundtrip_sigset_v1_two_labels(self): + """Test writing and reading back sigset (v1) with two labels""" # Create signature struct So = SigSet() @@ -164,8 +166,8 @@ def test_roundtrip_sigset_v1_two_bands(self): # Fill sigset struct with data So.title = ReturnString("Signature title") - So.bandrefs[0] = ctypes.create_string_buffer(b"The_Doors") - So.bandrefs[1] = ctypes.create_string_buffer(b"The_Who") + So.semantic_labels[0] = ctypes.create_string_buffer(b"The_Doors") + So.semantic_labels[1] = ctypes.create_string_buffer(b"The_Who") So.ClassSig[0].used = 1 So.ClassSig[0].classnum = 2 So.ClassSig[0].title = ReturnString("1st class") @@ -192,10 +194,14 @@ def test_roundtrip_sigset_v1_two_bands(self): self.assertEqual(ret, 1) self.assertEqual(utils.decode(Sn.title), "Signature title") self.assertEqual(Sn.nbands, 2) - bandref = utils.decode(ctypes.cast(Sn.bandrefs[0], ctypes.c_char_p).value) - self.assertEqual(bandref, "The_Doors") - bandref = utils.decode(ctypes.cast(Sn.bandrefs[1], ctypes.c_char_p).value) - self.assertEqual(bandref, "The_Who") + semantic_label = utils.decode( + ctypes.cast(Sn.semantic_labels[0], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label, "The_Doors") + semantic_label = utils.decode( + ctypes.cast(Sn.semantic_label[1], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label, "The_Who") self.assertEqual(Sn.nclasses, 1) self.assertEqual(Sn.ClassSig[0].nsubclasses, 1) self.assertEqual(Sn.ClassSig[0].used, 1) @@ -214,23 +220,23 @@ def test_roundtrip_sigset_v1_two_bands(self): # SigSet does not have free function -class SortSigSetByBandrefTest(TestCase): +class SortSigSetBySemanticLabelTest(TestCase): @classmethod def setUpClass(cls): cls.libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("c")) cls.mapset = Mapset().name cls.map1 = tempname(10) - cls.bandref1 = "The_Doors" + cls.semantic_label1 = "The_Doors" cls.map2 = tempname(10) - cls.bandref2 = "The_Who" + cls.semantic_label2 = "The_Who" cls.map3 = tempname(10) cls.use_temp_region() cls.runModule("g.region", n=1, s=0, e=1, w=0, res=1) cls.runModule("r.mapcalc", expression=f"{cls.map1} = 1") cls.runModule("r.mapcalc", expression=f"{cls.map2} = 1") cls.runModule("r.mapcalc", expression=f"{cls.map3} = 1") - Rast_write_bandref(cls.map1, cls.bandref1) - Rast_write_bandref(cls.map2, cls.bandref2) + Rast_write_semantic_label(cls.map1, cls.semantic_label1) + Rast_write_semantic_label(cls.map2, cls.semantic_label2) @classmethod def tearDownClass(cls): @@ -255,7 +261,7 @@ def test_symmetric_complete_difference(self): I_NewSubSig(ctypes.byref(S), ctypes.byref(S.ClassSig[0])) self.assertEqual(S.ClassSig[0].nsubclasses, 1) S.title = ReturnString("Signature title") - S.bandrefs[0] = ctypes.create_string_buffer(b"The_Troggs") + S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Troggs") S.ClassSig[0].used = 1 S.ClassSig[0].classnum = 2 S.ClassSig[0].title = ReturnString("1st class") @@ -265,7 +271,7 @@ def test_symmetric_complete_difference(self): S.ClassSig[0].SubSig[0].R[0][0] = 69.69 # This should result in two error strings in ret - ret = I_SortSigSetByBandref(ctypes.byref(S), ctypes.byref(R)) + ret = I_SortSigSetBySemanticLabel(ctypes.byref(S), ctypes.byref(R)) self.assertTrue(bool(ret)) sig_err = utils.decode(ctypes.cast(ret[0], ctypes.c_char_p).value) ref_err = utils.decode(ctypes.cast(ret[1], ctypes.c_char_p).value) @@ -300,7 +306,7 @@ def test_asymmetric_complete_difference(self): I_NewSubSig(ctypes.byref(S), ctypes.byref(S.ClassSig[0])) self.assertEqual(S.ClassSig[0].nsubclasses, 1) S.title = ReturnString("Signature title") - S.bandrefs[0] = ctypes.create_string_buffer(b"The_Troggs") + S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Troggs") S.ClassSig[0].used = 1 S.ClassSig[0].classnum = 2 S.ClassSig[0].title = ReturnString("1st class") @@ -310,7 +316,7 @@ def test_asymmetric_complete_difference(self): S.ClassSig[0].SubSig[0].R[0][0] = 69.69 # This should result in two error strings in ret - ret = I_SortSigSetByBandref(ctypes.byref(S), ctypes.byref(R)) + ret = I_SortSigSetBySemanticLabel(ctypes.byref(S), ctypes.byref(R)) self.assertTrue(bool(ret)) sig_err = utils.decode(ctypes.cast(ret[0], ctypes.c_char_p).value) ref_err = utils.decode(ctypes.cast(ret[1], ctypes.c_char_p).value) @@ -326,7 +332,7 @@ def test_asymmetric_complete_difference(self): self.libc.free(ret[1]) self.libc.free(ret) - def test_missing_bandref(self): + def test_missing_label(self): # Prepare imagery group reference struct R = Ref() I_init_group_ref(ctypes.byref(R)) @@ -346,7 +352,7 @@ def test_missing_bandref(self): I_NewSubSig(ctypes.byref(S), ctypes.byref(S.ClassSig[0])) self.assertEqual(S.ClassSig[0].nsubclasses, 1) S.title = ReturnString("Signature title") - S.bandrefs[0] = ctypes.create_string_buffer(b"The_Who") + S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Who") S.ClassSig[0].used = 1 S.ClassSig[0].classnum = 2 S.ClassSig[0].title = ReturnString("1st class") @@ -356,17 +362,17 @@ def test_missing_bandref(self): S.ClassSig[0].SubSig[0].R[0][0] = 69.69 # This should result in two error strings in ret - ret = I_SortSigSetByBandref(ctypes.byref(S), ctypes.byref(R)) + ret = I_SortSigSetBySemanticLabel(ctypes.byref(S), ctypes.byref(R)) self.assertTrue(bool(ret)) sig_err = utils.decode(ctypes.cast(ret[0], ctypes.c_char_p).value) ref_err = utils.decode(ctypes.cast(ret[1], ctypes.c_char_p).value) self.assertEqual( sig_err, - ",," - + ",," - + ",," - + ",," - + "", + ",," + + ",," + + ",," + + ",," + + "", ) self.assertEqual(ref_err, f"The_Doors,{self.map3}") @@ -395,7 +401,7 @@ def test_single_complete_match(self): I_NewSubSig(ctypes.byref(S), ctypes.byref(S.ClassSig[0])) self.assertEqual(S.ClassSig[0].nsubclasses, 1) S.title = ReturnString("Signature title") - S.bandrefs[0] = ctypes.create_string_buffer(b"The_Doors") + S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Doors") S.ClassSig[0].used = 1 S.ClassSig[0].classnum = 2 S.ClassSig[0].title = ReturnString("1st class") @@ -405,10 +411,12 @@ def test_single_complete_match(self): S.ClassSig[0].SubSig[0].R[0][0] = 69.69 # This should result in returning NULL - ret = I_SortSigSetByBandref(ctypes.byref(S), ctypes.byref(R)) + ret = I_SortSigSetBySemanticLabel(ctypes.byref(S), ctypes.byref(R)) self.assertFalse(bool(ret)) - bandref = utils.decode(ctypes.cast(S.bandrefs[0], ctypes.c_char_p).value) - self.assertEqual(bandref, "The_Doors") + semantic_label = utils.decode( + ctypes.cast(S.semantic_labels[0], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label, "The_Doors") self.assertEqual(S.ClassSig[0].SubSig[0].pi, 3.14) self.assertEqual(S.ClassSig[0].SubSig[0].means[0], 42.42) self.assertEqual(S.ClassSig[0].SubSig[0].R[0][0], 69.69) @@ -440,8 +448,8 @@ def test_double_complete_match_reorder(self): I_NewSubSig(ctypes.byref(S), ctypes.byref(S.ClassSig[0])) self.assertEqual(S.ClassSig[0].nsubclasses, 1) S.title = ReturnString("Signature title") - S.bandrefs[0] = ctypes.create_string_buffer(b"The_Who") - S.bandrefs[1] = ctypes.create_string_buffer(b"The_Doors") + S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Who") + S.semantic_labels[1] = ctypes.create_string_buffer(b"The_Doors") S.ClassSig[0].used = 1 S.ClassSig[0].classnum = 2 S.ClassSig[0].title = ReturnString("1st class") @@ -455,16 +463,20 @@ def test_double_complete_match_reorder(self): S.ClassSig[0].SubSig[0].R[1][1] = -96.96 # This should result in returning NULL - ret = I_SortSigSetByBandref(ctypes.byref(S), ctypes.byref(R)) + ret = I_SortSigSetBysemantic_label(ctypes.byref(S), ctypes.byref(R)) self.assertFalse(bool(ret)) # Band references and sig items should be swapped # Static items self.assertEqual(S.ClassSig[0].SubSig[0].pi, 3.14) # Reordered items - bandref1 = utils.decode(ctypes.cast(S.bandrefs[0], ctypes.c_char_p).value) - self.assertEqual(bandref1, "The_Doors") - bandref2 = utils.decode(ctypes.cast(S.bandrefs[1], ctypes.c_char_p).value) - self.assertEqual(bandref2, "The_Who") + semantic_label1 = utils.decode( + ctypes.cast(S.semantic_labels[0], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label1, "The_Doors") + semantic_label2 = utils.decode( + ctypes.cast(S.semantic_labels[1], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label2, "The_Who") self.assertEqual(S.ClassSig[0].SubSig[0].means[0], 24.24) self.assertEqual(S.ClassSig[0].SubSig[0].means[1], 42.42) self.assertEqual(S.ClassSig[0].SubSig[0].R[0][0], -96.96) @@ -499,8 +511,8 @@ def test_double_complete_match_same_order(self): I_NewSubSig(ctypes.byref(S), ctypes.byref(S.ClassSig[0])) self.assertEqual(S.ClassSig[0].nsubclasses, 1) S.title = ReturnString("Signature title") - S.bandrefs[0] = ctypes.create_string_buffer(b"The_Who") - S.bandrefs[1] = ctypes.create_string_buffer(b"The_Doors") + S.semantic_labels[0] = ctypes.create_string_buffer(b"The_Who") + S.semantic_labels[1] = ctypes.create_string_buffer(b"The_Doors") S.ClassSig[0].used = 1 S.ClassSig[0].classnum = 2 S.ClassSig[0].title = ReturnString("1st class") @@ -514,16 +526,20 @@ def test_double_complete_match_same_order(self): S.ClassSig[0].SubSig[0].R[1][1] = -96.96 # This should result in returning NULL - ret = I_SortSigSetByBandref(ctypes.byref(S), ctypes.byref(R)) + ret = I_SortSigSetBysemantic_label(ctypes.byref(S), ctypes.byref(R)) self.assertFalse(bool(ret)) # Band references and sig items should not be swapped # Static items self.assertEqual(S.ClassSig[0].SubSig[0].pi, 3.14) # Reordered items - bandref1 = utils.decode(ctypes.cast(S.bandrefs[0], ctypes.c_char_p).value) - self.assertEqual(bandref1, "The_Who") - bandref2 = utils.decode(ctypes.cast(S.bandrefs[1], ctypes.c_char_p).value) - self.assertEqual(bandref2, "The_Doors") + semantic_label1 = utils.decode( + ctypes.cast(S.semantic_labels[0], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label1, "The_Who") + semantic_label2 = utils.decode( + ctypes.cast(S.semantic_labels[1], ctypes.c_char_p).value + ) + self.assertEqual(semantic_label2, "The_Doors") self.assertEqual(S.ClassSig[0].SubSig[0].means[0], 42.42) self.assertEqual(S.ClassSig[0].SubSig[0].means[1], 24.24) self.assertEqual(S.ClassSig[0].SubSig[0].R[0][0], 69.69) diff --git a/lib/raster/raster_metadata.c b/lib/raster/raster_metadata.c index 30325ae26c2..534892c2d01 100644 --- a/lib/raster/raster_metadata.c +++ b/lib/raster/raster_metadata.c @@ -2,7 +2,7 @@ \file lib/raster/raster_metadata.c \brief Raster library - Functions to read and write raster "units", - "band reference" and "vertical datum" meta-data info + "semantic label" and "vertical datum" meta-data info (C) 2007-2009, 2021 by Hamish Bowman, Maris Nartiss, and the GRASS Development Team @@ -83,90 +83,90 @@ void Rast_write_vdatum(const char *name, const char *str) } /*! - * \brief Get a raster map's band reference metadata string + * \brief Get a raster map semantic label metadata string * - * Read the raster's band reference metadata file and put string in str + * Read raster semantic label metadata file and put string in to str * * \param name raster map name * \param mapset mapset name * - * \return string representing band reference on success + * \return string representing semantic label on success * \return NULL on error */ -char *Rast_read_bandref(const char *name, const char *mapset) +char *Rast_read_semantic_label(const char *name, const char *mapset) { - return misc_read_line("bandref", name, mapset); + return misc_read_line("semantic_label", name, mapset); } /*! - * \brief Get a raster map band reference or fall back to its name + * \brief Get a raster map semantic label or fall back to its name * - * Use this function if a band reference is needed but not mandated. + * Use this function if a semantic label is needed but not mandated. * * \param name raster map name * \param mapset mapset name * - * \return string representing band reference or map name + * \return string representing semantic label or map name */ -char *Rast_get_bandref_or_name(const char *name, const char *mapset) { +char *Rast_get_semantic_label_or_name(const char *name, const char *mapset) { char *buff; - buff = Rast_read_bandref(name, mapset); + buff = Rast_read_semantic_label(name, mapset); return buff ? buff : G_store(name); } /*! - * \brief Write a string into a raster's band reference metadata file + * \brief Write a string into a rasters semantic label metadata file * * Raster map must exist in the current mapset. * - * It is up to the caller to validate band reference string in advance - * with Rast_legal_bandref(). + * It is up to the caller to validate semantic label string in advance + * with Rast_legal_semantic_label(). * * \param name raster map name * \param str string containing data to be written */ -void Rast_write_bandref(const char *name, const char *str) +void Rast_write_semantic_label(const char *name, const char *str) { - misc_write_line("bandref", name, str); + misc_write_line("semantic_label", name, str); } /*! - * \brief Check for legal band reference + * \brief Check for legal semantic label * - * Legal band identifiers must be legal GRASS file names. - * They are in format _. - * Band identifiers are capped in legth to GNAME_MAX. + * Legal semantic label must be a legal GRASS file name. + * Semantic labels are capped in legth to GNAME_MAX. * - * This function will return false if provided band id is not considered - * to be valid. - * This function does not check if band id maps to any entry in band - * metadata files as not all band id's have files with extra metadata. + * This function will return false if provided semantic label is not + * considered to be valid. + * This function does not check if semantic label maps to any entry in + * metadata files of semantic labels as not all semantic labels have + * files with extra metadata. * * The function prints a warning on error. * - * \param bandref band reference to check + * \param semantic label reference to check * * \return true success * \return false failure */ -bool Rast_legal_bandref(const char *bandref) +bool Rast_legal_semantic_label(const char *semantic_label) { const char *s; - if (strlen(bandref) >= GNAME_MAX) { - G_warning(_("Band reference is too long")); + if (strlen(semantic_label) >= GNAME_MAX) { + G_warning(_("Semantic label is too long")); return false; } - if (G_legal_filename(bandref) != 1) + if (G_legal_filename(semantic_label) != 1) return false; - s = bandref; + s = semantic_label; while (*s) { if (!((*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z') || (*s >= '0' && *s <= '9') || *s == '_' || *s == '-')) { - G_warning(_("Character '%c' not allowed in band reference."), *s); + G_warning(_("Character '%c' not allowed in a semantic label."), *s); return false; } s++; diff --git a/lib/raster/testsuite/test_raster_metadata.py b/lib/raster/testsuite/test_raster_metadata.py index bdd2b7aeb70..7da2c0fe4cf 100644 --- a/lib/raster/testsuite/test_raster_metadata.py +++ b/lib/raster/testsuite/test_raster_metadata.py @@ -20,61 +20,61 @@ from grass.lib.gis import G_remove_misc from grass.lib.raster import ( - Rast_legal_bandref, - Rast_read_bandref, - Rast_get_bandref_or_name, - Rast_write_bandref, + Rast_legal_semantic_label, + Rast_read_semantic_label, + Rast_get_semantic_label_or_name, + Rast_write_semantic_label, ) class RastLegalBandIdTestCase(TestCase): def test_empty_name(self): - ret = Rast_legal_bandref("") + ret = Rast_legal_semantic_label("") self.assertEqual(ret, False) - ret = Rast_legal_bandref(" ") + ret = Rast_legal_semantic_label(" ") self.assertEqual(ret, False) def test_illegal_name(self): - ret = Rast_legal_bandref(".a") + ret = Rast_legal_semantic_label(".a") self.assertEqual(ret, False) - ret = Rast_legal_bandref("a/b") + ret = Rast_legal_semantic_label("a/b") self.assertEqual(ret, False) - ret = Rast_legal_bandref("a@b") + ret = Rast_legal_semantic_label("a@b") self.assertEqual(ret, False) - ret = Rast_legal_bandref("a#b") + ret = Rast_legal_semantic_label("a#b") self.assertEqual(ret, False) def test_too_long(self): - ret = Rast_legal_bandref( + ret = Rast_legal_semantic_label( "a_" + "".join(random.choices(string.ascii_letters, k=253)) ) self.assertEqual(ret, True) - ret = Rast_legal_bandref( + ret = Rast_legal_semantic_label( "a_" + "".join(random.choices(string.ascii_letters, k=254)) ) self.assertEqual(ret, False) def test_good_name(self): - ret = Rast_legal_bandref("1") + ret = Rast_legal_semantic_label("1") self.assertEqual(ret, True) - ret = Rast_legal_bandref("1a") + ret = Rast_legal_semantic_label("1a") self.assertEqual(ret, True) - ret = Rast_legal_bandref("clouds") + ret = Rast_legal_semantic_label("clouds") self.assertEqual(ret, True) - ret = Rast_legal_bandref("rededge1") + ret = Rast_legal_semantic_label("rededge1") self.assertEqual(ret, True) - ret = Rast_legal_bandref("S2_1") + ret = Rast_legal_semantic_label("S2_1") self.assertEqual(ret, True) - ret = Rast_legal_bandref("GRASS_aspect_deg") + ret = Rast_legal_semantic_label("GRASS_aspect_deg") self.assertEqual(ret, True) -class RastBandReferenceTestCase(TestCase): +class Rastsemantic_labelerenceTestCase(TestCase): @classmethod def setUpClass(cls): cls.map = tempname(10) cls.mapset = Mapset().name - cls.bandref = "The_Doors" + cls.semantic_label = "The_Doors" cls.use_temp_region() cls.runModule("g.region", n=1, s=0, e=1, w=0, res=1) cls.runModule("r.mapcalc", expression="{} = 1".format(cls.map)) @@ -84,29 +84,29 @@ def tearDownClass(cls): cls.del_temp_region() cls.runModule("g.remove", flags="f", type="raster", name=cls.map) - def test_read_bandref_present(self): - Rast_write_bandref(self.map, self.bandref) - ret = utils.decode(Rast_read_bandref(self.map, self.mapset)) - self.assertEqual(ret, self.bandref) + def test_read_semantic_label_present(self): + Rast_write_semantic_label(self.map, self.semantic_label) + ret = utils.decode(Rast_read_semantic_label(self.map, self.mapset)) + self.assertEqual(ret, self.semantic_label) - def test_read_bandref_absent(self): - G_remove_misc("cell_misc", "bandref", self.map) - ret = Rast_read_bandref(self.map, self.mapset) + def test_read_semantic_label_absent(self): + G_remove_misc("cell_misc", "semantic_label", self.map) + ret = Rast_read_semantic_label(self.map, self.mapset) self.assertFalse(bool(ret)) - def test_write_bandref(self): - G_remove_misc("cell_misc", "bandref", self.map) - Rast_write_bandref(self.map, self.bandref) - ret = utils.decode(Rast_read_bandref(self.map, self.mapset)) - self.assertEqual(ret, self.bandref) + def test_write_semantic_label(self): + G_remove_misc("cell_misc", "semantic_label", self.map) + Rast_write_semantic_label(self.map, self.semantic_label) + ret = utils.decode(Rast_read_semantic_label(self.map, self.mapset)) + self.assertEqual(ret, self.semantic_label) - def test_get_bandref_or_name(self): - G_remove_misc("cell_misc", "bandref", self.map) - ret = utils.decode(Rast_get_bandref_or_name(self.map, self.mapset)) + def test_get_semantic_label_or_name(self): + G_remove_misc("cell_misc", "semantic_label", self.map) + ret = utils.decode(Rast_get_semantic_label_or_name(self.map, self.mapset)) self.assertEqual(ret, self.map) - Rast_write_bandref(self.map, self.bandref) - ret = utils.decode(Rast_get_bandref_or_name(self.map, self.mapset)) - self.assertEqual(ret, self.bandref) + Rast_write_semantic_label(self.map, self.semantic_label) + ret = utils.decode(Rast_get_semantic_label_or_name(self.map, self.mapset)) + self.assertEqual(ret, self.semantic_label) if __name__ == "__main__": From 672186acc658bf008f387dfba63d72c3d3713eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C4=81ris=20Narti=C5=A1s?= Date: Mon, 11 Oct 2021 20:55:20 +0300 Subject: [PATCH 02/11] Band reference -> semantic label (continued) --- imagery/i.cca/i.cca.html | 2 +- imagery/i.cca/main.c | 4 +- imagery/i.cluster/global.h | 2 +- imagery/i.cluster/i.cluster.html | 32 +++--- imagery/i.cluster/main.c | 4 +- imagery/i.cluster/open_files.c | 12 +- imagery/i.gensig/i.gensig.html | 14 +-- imagery/i.gensig/openfiles.c | 8 +- imagery/i.gensigset/i.gensigset.html | 8 +- imagery/i.gensigset/openfiles.c | 6 +- imagery/i.maxlik/i.maxlik.html | 2 +- imagery/i.maxlik/open.c | 4 +- imagery/i.smap/i.smap.html | 28 ++--- imagery/i.smap/openfiles.c | 4 +- imagery/imageryintro.html | 2 +- include/grass/defs/imagery.h | 4 +- include/grass/defs/raster.h | 8 +- include/grass/imagery.h | 4 +- lib/imagery/iclass_signatures.c | 2 +- lib/imagery/sig.c | 100 ++++++++--------- lib/imagery/sigset.c | 106 +++++++++--------- python/grass/pygrass/raster/abstract.py | 30 ++--- .../grass/temporal/c_libraries_interface.py | 80 ++++++------- python/grass/temporal/extract.py | 8 +- python/grass/temporal/metadata.py | 34 +++--- .../ctypesgencore/parser/lextab.py | 8 ++ raster/r.info/main.c | 10 +- raster/r.info/r.info.html | 2 +- raster/r.support/main.c | 48 ++++---- raster/r.support/r.support.html | 14 +-- raster/r.support/testsuite/test_r_support.py | 30 ++--- scripts/i.band/i.band.html | 36 +++--- scripts/i.band/i.band.py | 64 +++++------ scripts/i.band/testsuite/test_i_band.py | 24 ++-- 34 files changed, 375 insertions(+), 369 deletions(-) create mode 100644 python/libgrass_interface_generator/ctypesgencore/parser/lextab.py diff --git a/imagery/i.cca/i.cca.html b/imagery/i.cca/i.cca.html index e597b8531a0..3daaaa998c8 100644 --- a/imagery/i.cca/i.cca.html +++ b/imagery/i.cca/i.cca.html @@ -80,7 +80,7 @@

AUTHORS

Ali R. Vali, University of Texas
-Band reference support: Maris Nartiss, +Semantic label support: Maris Nartiss, University of Latvia