Browse Source

Rename band references to semantic labels (#1928)

Rename band references to semantic labels (fixes #1868)
Māris Nartišs 3 years ago
parent
commit
0e43bf349d
61 changed files with 793 additions and 753 deletions
  1. 1 1
      imagery/i.cca/i.cca.html
  2. 2 2
      imagery/i.cca/main.c
  3. 1 1
      imagery/i.cluster/global.h
  4. 16 16
      imagery/i.cluster/i.cluster.html
  5. 2 2
      imagery/i.cluster/main.c
  6. 6 6
      imagery/i.cluster/open_files.c
  7. 7 7
      imagery/i.gensig/i.gensig.html
  8. 4 4
      imagery/i.gensig/openfiles.c
  9. 4 4
      imagery/i.gensigset/i.gensigset.html
  10. 3 3
      imagery/i.gensigset/openfiles.c
  11. 1 1
      imagery/i.maxlik/i.maxlik.html
  12. 2 2
      imagery/i.maxlik/open.c
  13. 14 14
      imagery/i.smap/i.smap.html
  14. 2 2
      imagery/i.smap/openfiles.c
  15. 1 1
      imagery/imageryintro.html
  16. 2 2
      include/grass/defs/imagery.h
  17. 4 4
      include/grass/defs/raster.h
  18. 2 2
      include/grass/imagery.h
  19. 1 1
      lib/imagery/iclass_signatures.c
  20. 50 50
      lib/imagery/sig.c
  21. 53 53
      lib/imagery/sigset.c
  22. 98 76
      lib/imagery/testsuite/test_imagery_sigfile.py
  23. 71 55
      lib/imagery/testsuite/test_imagery_sigsetfile.py
  24. 31 31
      lib/raster/raster_metadata.c
  25. 38 38
      lib/raster/testsuite/test_raster_metadata.py
  26. 1 1
      lib/temporal/SQL/raster_metadata_table.sql
  27. 2 2
      lib/temporal/SQL/raster_views.sql
  28. 1 1
      lib/temporal/SQL/update_strds_metadata_template.sql
  29. 1 1
      lib/temporal/SQL/upgrade_db_2_to_3.sql
  30. 1 1
      python/grass/Makefile
  31. 0 1
      python/grass/bandref/__init__.py
  32. 15 15
      python/grass/pygrass/raster/abstract.py
  33. 1 1
      python/grass/bandref/Makefile
  34. 1 0
      python/grass/semantic_label/__init__.py
  35. 55 51
      python/grass/bandref/reader.py
  36. 4 4
      python/grass/temporal/abstract_map_dataset.py
  37. 21 21
      python/grass/temporal/abstract_space_time_dataset.py
  38. 40 40
      python/grass/temporal/c_libraries_interface.py
  39. 4 4
      python/grass/temporal/extract.py
  40. 1 1
      python/grass/temporal/mapcalc.py
  41. 17 17
      python/grass/temporal/metadata.py
  42. 6 6
      python/grass/temporal/open_stds.py
  43. 20 20
      python/grass/temporal/register.py
  44. 27 27
      python/grass/temporal/space_time_datasets.py
  45. 5 5
      raster/r.info/main.c
  46. 1 1
      raster/r.info/r.info.html
  47. 24 24
      raster/r.support/main.c
  48. 6 8
      raster/r.support/r.support.html
  49. 17 15
      raster/r.support/testsuite/test_r_support.py
  50. 8 13
      scripts/g.bands/g.bands.py
  51. 2 2
      scripts/g.bands/testsuite/test_g_bands.py
  52. 18 18
      scripts/i.band/i.band.html
  53. 33 34
      scripts/i.band/i.band.py
  54. 16 12
      scripts/i.band/testsuite/test_i_band.py
  55. 4 4
      temporal/t.info/t.info.html
  56. 2 2
      temporal/t.list/t.list.py
  57. 8 8
      temporal/t.rast.list/t.rast.list.html
  58. 2 2
      temporal/t.rast.list/t.rast.list.py
  59. 4 4
      temporal/t.rast.mapcalc/t.rast.mapcalc.html
  60. 8 8
      temporal/t.register/t.register.html
  61. 1 1
      temporal/t.upgrade/t.upgrade.html

+ 1 - 1
imagery/i.cca/i.cca.html

@@ -80,7 +80,7 @@ Central Washington University
 Ali R. Vali, 
 University of Texas
 <br>
-Band reference support: Maris Nartiss,
+Semantic label support: Maris Nartiss,
 University of Latvia
 
 <!--

+ 2 - 2
imagery/i.cca/main.c

@@ -135,9 +135,9 @@ int main(int argc, char *argv[])
     if (nclass < 2)
 	G_fatal_error(_("Need at least two signatures in signature file."));
 
-    err = I_sort_signatures_by_bandref(&sigs, &refs);
+    err = I_sort_signatures_by_semantic_label(&sigs, &refs);
     if (err)
-        G_fatal_error(_("Signature – group member band reference mismatch.\n"
+        G_fatal_error(_("Signature – group member semantic label mismatch.\n"
             "Extra signatures for bands: %s\n"
             "Imagery group bands without signatures: %s"),
             err[0] ? err[0] : _("none"),

+ 1 - 1
imagery/i.cluster/global.h

@@ -26,7 +26,7 @@ extern int mcs;
 extern char *group;
 extern char *subgroup;
 extern struct Ref ref;
-extern char **bandrefs;
+extern char **semantic_labels;
 extern char outsigfile[GNAME_MAX + GMAPSET_MAX];
 extern char *insigfile;
 extern char *reportfile;

+ 16 - 16
imagery/i.cluster/i.cluster.html

@@ -73,12 +73,12 @@ set to their default values.
 
 <p>
 For all raster maps used to generate signature file it is recommended
-to have band reference set.
+to have semantic label set.
 Use <em><a href="r.support.html">r.support</a></em> to set
-band references of each member of the imagery group.
+semantc labels of each member of the imagery group.
 Signatures generated for one scene are suitable for classification
 of other scenes as long as they consist of same raster bands
-(band references match). If band references are not set, it will be
+(semantic labels match). If semantic labels are not set, it will be
 possible to use obtained signature file to classify only the same
 imagery group used for generating signatures.
 
@@ -287,22 +287,22 @@ The signature file obtained in the example above will allow
 to classify the current imagery group only (lsat7_2002).
 If the user would like to re-use the signature file for the
 classification of different imagery group(s), they can set
-band references for each group member beforehand, i.e.,
+semantic labels for each group member beforehand, i.e.,
 before generating the signature files.
-Band references are set by means of <em>r.support</em>
+Semantic labels are set by means of <em>r.support</em>
 as shown below:
 
 <div class="code"><pre>
-# Define band references for all LANDSAT bands
-r.support map=lsat7_2002_10 bandref=TM7_1
-r.support map=lsat7_2002_20 bandref=TM7_2
-r.support map=lsat7_2002_30 bandref=TM7_3
-r.support map=lsat7_2002_40 bandref=TM7_4
-r.support map=lsat7_2002_50 bandref=TM7_5
-r.support map=lsat7_2002_61 bandref=TM7_61
-r.support map=lsat7_2002_62 bandref=TM7_62
-r.support map=lsat7_2002_70 bandref=TM7_7
-r.support map=lsat7_2002_80 bandref=TM7_8
+# Define semantic labels for all LANDSAT bands
+r.support map=lsat7_2002_10 semantic_label=TM7_1
+r.support map=lsat7_2002_20 semantic_label=TM7_2
+r.support map=lsat7_2002_30 semantic_label=TM7_3
+r.support map=lsat7_2002_40 semantic_label=TM7_4
+r.support map=lsat7_2002_50 semantic_label=TM7_5
+r.support map=lsat7_2002_61 semantic_label=TM7_61
+r.support map=lsat7_2002_62 semantic_label=TM7_62
+r.support map=lsat7_2002_70 semantic_label=TM7_7
+r.support map=lsat7_2002_80 semantic_label=TM7_8
 </pre></div>
 
 <h2>SEE ALSO</h2>
@@ -335,7 +335,7 @@ U.S. Army Construction Engineering Research Laboratory
 Tao Wen, 
 University of Illinois at Urbana-Champaign, Illinois
 <br>
-Band reference support: Maris Nartiss,
+Semantic label support: Maris Nartiss,
 University of Latvia
 
 <!--

+ 2 - 2
imagery/i.cluster/main.c

@@ -39,7 +39,7 @@ int mcs;
 char *group;
 char *subgroup;
 struct Ref ref;
-char **bandrefs;
+char **semantic_labels;
 char outsigfile[GNAME_MAX + GMAPSET_MAX];
 char *insigfile;
 char *reportfile;
@@ -334,7 +334,7 @@ int main(int argc, char *argv[])
     if ((fd =
 	 I_fopen_signature_file_new(outsigfile)) != NULL) {
         for (unsigned int i = C.S.nbands; i--;)
-            C.S.bandrefs[i] = bandrefs[i];
+            C.S.semantic_labels[i] = semantic_labels[i];
 	I_write_signatures(fd, &C.S);
 	fclose(fd);
     }

+ 6 - 6
imagery/i.cluster/open_files.c

@@ -7,7 +7,7 @@
 
 int open_files(void)
 {
-    char *name, *mapset, **err, *bandref;
+    char *name, *mapset, **err, *semantic_label;
     FILE *fd;
     int n, missing;
 
@@ -15,7 +15,7 @@ int open_files(void)
     I_free_group_ref(&ref);
     I_get_subgroup_ref(group, subgroup, &ref);
 
-    bandrefs = (char **)G_malloc(ref.nfiles * sizeof(char **));
+    semantic_labels = (char **)G_malloc(ref.nfiles * sizeof(char **));
     missing = 0;
     for (n = 0; n < ref.nfiles; n++) {
 	name = ref.file[n].name;
@@ -25,8 +25,8 @@ int open_files(void)
 	    G_warning(_("Raster map <%s> do not exists in subgroup <%s>"),
 		      G_fully_qualified_name(name, mapset), subgroup);
         }
-        bandref = Rast_get_bandref_or_name(ref.file[n].name, ref.file[n].mapset);
-        bandrefs[n] = G_store(bandref);
+        semantic_label = Rast_get_semantic_label_or_name(ref.file[n].name, ref.file[n].mapset);
+        semantic_labels[n] = G_store(semantic_label);
     }
     if (missing)
 	G_fatal_error(_("No raster maps found"));
@@ -66,9 +66,9 @@ int open_files(void)
 	    G_fatal_error(_("<%s> has too many signatures (limit is 255)"),
 			  insigfile);
 
-        err = I_sort_signatures_by_bandref(&in_sig, &ref);
+        err = I_sort_signatures_by_semantic_label(&in_sig, &ref);
         if (err)
-            G_fatal_error(_("Signature – group member band reference mismatch.\n"
+            G_fatal_error(_("Signature – group member semantic label mismatch.\n"
                 "Extra signatures for bands: %s\n"
                 "Imagery group bands without signatures: %s"),
                 err[0] ? err[0] : _("none"),

+ 7 - 7
imagery/i.gensig/i.gensig.html

@@ -22,12 +22,12 @@ The user would then execute the GRASS program
 to actually create the final classified map.
 
 <p>
-All raster maps used to generate signature file must have band reference
+All raster maps used to generate signature file can have semantic label
 set. Use <em><a href="r.support.html">r.support</a></em> to set
-band references of each member of the imagery group.
+semantic labels of each member of the imagery group.
 Signatures generated for one scene are suitable for classification
 of other scenes as long as they consist of same raster bands
-(band references match).
+(semantic labels match).
 
 <h2>OPTIONS</h2>
 
@@ -75,7 +75,7 @@ This is the resultant signature file (containing the means
 and covariance matrices) for each class in the training map
 that is associated with the band files in the subgroup
 select (see <a href="#subgroup">above</a>). Resultant singature file
-can be used with any other imagery group as long as band references
+can be used with any other imagery group as long as semantic labels
 match.
 </dl>
 
@@ -91,7 +91,7 @@ SIG file "lsat7_2000_gensig":
 <div class="code"><pre>
  1 1
  2 #
- 3 Band_reference1
+ 3 Semantic_label1
  4 #water
  5 4186
  6 67.9508 48.7346 37.8915 15.3129 13.8473 12.0855 
@@ -106,7 +106,7 @@ SIG file "lsat7_2000_gensig":
 <ul>
 <li> Line 1: version number (currently always 1)
 <li> Line 2: text label
-<li> Line 3: Space separated list of band references
+<li> Line 3: Space separated list of semantic labels
 <li> Line 4: text label of class
 <li> Line 5: number of points in class
 <li> Line 6: mean values per band of the class
@@ -132,7 +132,7 @@ SIG file "lsat7_2000_gensig":
 Michael Shapiro,
 U.S.Army Construction Engineering Research Laboratory
 <br>
-Band reference support: Maris Nartiss,
+Semantic label support: Maris Nartiss,
 University of Latvia
 
 <!--

+ 4 - 4
imagery/i.gensig/openfiles.c

@@ -11,7 +11,7 @@
 int openfiles(struct parms *parms, struct files *files, struct Signature *S)
 {
     struct Ref Ref;		/* subgroup reference list */
-    const char *mapset, *bandref;
+    const char *mapset, *semantic_label;
     int n;
 
 
@@ -37,13 +37,13 @@ int openfiles(struct parms *parms, struct files *files, struct Signature *S)
     I_init_signatures(S, Ref.nfiles);
 
     /* open all maps for reading and
-       store band references of imagery group bands */
+       store semantic labels of imagery group bands */
     for (n = 0; n < Ref.nfiles; n++) {
 	files->band_fd[n] =
 	    Rast_open_old(Ref.file[n].name, Ref.file[n].mapset);
 	files->band_cell[n] = Rast_allocate_d_buf();
-        bandref = Rast_get_bandref_or_name(Ref.file[n].name, Ref.file[n].mapset);
-        S->bandrefs[n] = G_store(bandref);
+        semantic_label = Rast_get_semantic_label_or_name(Ref.file[n].name, Ref.file[n].mapset);
+        S->semantic_labels[n] = G_store(semantic_label);
     }
 
     I_free_group_ref(&Ref);

+ 4 - 4
imagery/i.gensigset/i.gensigset.html

@@ -20,12 +20,12 @@ final classified map.
 
 <p>
 For all raster maps used to generate signature file it is recommended
-to have band reference set.
+to have semantic label set.
 Use <em><a href="r.support.html">r.support</a></em> to set
-band references of each member of the imagery group.
+semantic labels of each member of the imagery group.
 Signatures generated for one scene are suitable for classification
 of other scenes as long as they consist of same raster bands
-(band references match). If band references are not set, it will be
+(semantic labels match). If semantic labels are not set, it will be
 possible to use obtained signature file to classify only the same
 imagery group used for generating signatures.
 
@@ -233,7 +233,7 @@ School of Electrical Engineering, Purdue University
 Michael Shapiro,
 U.S.Army Construction Engineering Research Laboratory
 <br>
-Band reference support: Maris Nartiss,
+Semantic label support: Maris Nartiss,
 University of Latvia
 
 <!--

+ 3 - 3
imagery/i.gensigset/openfiles.c

@@ -10,7 +10,7 @@
 int openfiles(struct parms *parms, struct files *files, struct SigSet *S)
 {
     struct Ref Ref;		/* subgroup reference list */
-    const char *mapset, *bandref;
+    const char *mapset, *semantic_label;
     int n;
 
 
@@ -41,8 +41,8 @@ int openfiles(struct parms *parms, struct files *files, struct SigSet *S)
 	files->band_fd[n] =
 	    Rast_open_old(Ref.file[n].name, Ref.file[n].mapset);
 	files->band_cell[n] = Rast_allocate_d_buf();
-        bandref = Rast_get_bandref_or_name(Ref.file[n].name, Ref.file[n].mapset);
-        S->bandrefs[n] = G_store(bandref);
+        semantic_label = Rast_get_semantic_label_or_name(Ref.file[n].name, Ref.file[n].mapset);
+        S->semantic_labels[n] = G_store(semantic_label);
     }
 
     I_free_group_ref(&Ref);

+ 1 - 1
imagery/i.maxlik/i.maxlik.html

@@ -153,7 +153,7 @@ Tao Wen,
 University of Illinois at Urbana-Champaign,
 Illinois
 <br>
-Band reference support: Maris Nartiss,
+Semantic label support: Maris Nartiss,
 University of Latvia
 
 <!--

+ 2 - 2
imagery/i.maxlik/open.c

@@ -46,9 +46,9 @@ int open_files(void)
 	G_fatal_error(_("<%s> has too many signatures (limit is 255)"),
 		      sigfile);
 
-    err = I_sort_signatures_by_bandref(&S, &Ref);
+    err = I_sort_signatures_by_semantic_label(&S, &Ref);
     if (err)
-        G_fatal_error(_("Signature – group member band reference mismatch.\n"
+        G_fatal_error(_("Signature – group member semantic label mismatch.\n"
             "Extra signatures for bands: %s\n"
             "Imagery group bands without signatures: %s"),
             err[0] ? err[0] : _("none"),

+ 14 - 14
imagery/i.smap/i.smap.html

@@ -176,22 +176,22 @@ The signature file obtained in the example above will allow
 to classify the current imagery group only (lsat7_2002).
 If the user would like to re-use the signature file for the
 classification of different imagery group(s), they can set
-band references for each group member beforehand, i.e.,
+semantic labels for each group member beforehand, i.e.,
 before generating the signature files.
-Band references are set by means of <em>r.support</em>
+Semantic labels are set by means of <em>r.support</em>
 as shown below:
 
 <div class="code"><pre>
-# Define band references for all LANDSAT bands
-r.support map=lsat7_2002_10 bandref=TM7_1
-r.support map=lsat7_2002_20 bandref=TM7_2
-r.support map=lsat7_2002_30 bandref=TM7_3
-r.support map=lsat7_2002_40 bandref=TM7_4
-r.support map=lsat7_2002_50 bandref=TM7_5
-r.support map=lsat7_2002_61 bandref=TM7_61
-r.support map=lsat7_2002_62 bandref=TM7_62
-r.support map=lsat7_2002_70 bandref=TM7_7
-r.support map=lsat7_2002_80 bandref=TM7_8
+# Define sematic labels for all LANDSAT bands
+r.support map=lsat7_2002_10 semantic_label=TM7_1
+r.support map=lsat7_2002_20 semantic_label=TM7_2
+r.support map=lsat7_2002_30 semantic_label=TM7_3
+r.support map=lsat7_2002_40 semantic_label=TM7_4
+r.support map=lsat7_2002_50 semantic_label=TM7_5
+r.support map=lsat7_2002_61 semantic_label=TM7_61
+r.support map=lsat7_2002_62 semantic_label=TM7_62
+r.support map=lsat7_2002_70 semantic_label=TM7_7
+r.support map=lsat7_2002_80 semantic_label=TM7_8
 </pre></div>
 
 <h2>REFERENCES</h2>
@@ -216,7 +216,7 @@ pp. III-565 - III-568, San Francisco, California, March 23-26, 1992.
 <h2>SEE ALSO</h2>
 
 <em>
-<a href="r.support.html">r.support</a></em> for setting band references,
+<a href="r.support.html">r.support</a></em> for setting semantic labels,
 <br>
 <em>
 <a href="i.group.html">i.group</a></em> for creating groups and subgroups
@@ -243,7 +243,7 @@ Michael Shapiro,
 U.S.Army Construction Engineering 
 Research Laboratory
 <br>
-Band reference support: Maris Nartiss,
+Semantic label support: Maris Nartiss,
 University of Latvia
 
 <!--

+ 2 - 2
imagery/i.smap/openfiles.c

@@ -37,9 +37,9 @@ int openfiles(struct parms *parms, struct files *files, struct SigSet *S)
 
     fclose(fd);
 
-    err = I_SortSigSetByBandref(S, &Ref);
+    err = I_SortSigSetBySemanticLabel(S, &Ref);
     if (err)
-        G_fatal_error(_("Signature – group member band reference mismatch.\n"
+        G_fatal_error(_("Signature – group member semantic label mismatch.\n"
             "Extra signatures for bands: %s\n"
             "Imagery group bands without signatures: %s"),
             err[0] ? err[0] : _("none"),

+ 1 - 1
imagery/imageryintro.html

@@ -184,7 +184,7 @@ calculated with <a href="r.covar.html">r.covar</a>.
 <p>
 Note - signatures generated for one scene are suitable for classification
 of other scenes as long as they consist of same raster bands
-(band references match). This comes handy when classifying multiple scenes
+(semantic labels match). This comes handy when classifying multiple scenes
 from a single sensor taken in different areas or different times.
 
 <h3>Image fusion</h3>

+ 2 - 2
include/grass/defs/imagery.h

@@ -163,7 +163,7 @@ int I_free_signatures(struct Signature *);
 int I_read_one_signature(FILE *, struct Signature *);
 int I_read_signatures(FILE *, struct Signature *);
 int I_write_signatures(FILE *, struct Signature *);
-char **I_sort_signatures_by_bandref(struct Signature *, const struct Ref *);
+char **I_sort_signatures_by_semantic_label(struct Signature *, const struct Ref *);
 
 /* sigfile.c */
 FILE *I_fopen_signature_file_new(const char *);
@@ -181,7 +181,7 @@ const char *I_GetSigTitle(const struct SigSet *);
 int I_SetClassTitle(struct ClassSig *, const char *);
 const char *I_GetClassTitle(const struct ClassSig *);
 int I_WriteSigSet(FILE *, const struct SigSet *);
-char **I_SortSigSetByBandref(struct SigSet *, const struct Ref *);
+char **I_SortSigSetBySemanticLabel(struct SigSet *, const struct Ref *);
 
 /* sigsetfile.c */
 FILE *I_fopen_sigset_file_new(const char *);

+ 4 - 4
include/grass/defs/raster.h

@@ -544,12 +544,12 @@ DCELL Rast_get_d_value(const void *, RASTER_MAP_TYPE);
 /* raster_metadata.c */
 char *Rast_read_units(const char *, const char *);
 char *Rast_read_vdatum(const char *, const char *);
-char *Rast_read_bandref(const char *, const char *);
-char *Rast_get_bandref_or_name(const char *, const char *);
+char *Rast_read_semantic_label(const char *, const char *);
+char *Rast_get_semantic_label_or_name(const char *, const char *);
 void Rast_write_units(const char *, const char *);
 void Rast_write_vdatum(const char *, const char *);
-void Rast_write_bandref(const char *, const char *);
-bool Rast_legal_bandref(const char *);
+void Rast_write_semantic_label(const char *, const char *);
+bool Rast_legal_semantic_label(const char *);
 
 /* rast_to_img_string.c */
 int Rast_map_to_img_str(char *, int, unsigned char*);

+ 2 - 2
include/grass/imagery.h

@@ -63,7 +63,7 @@ struct One_Sig
 struct Signature
 {
     int nbands;         /* band (imagery group member) count */
-    char **bandrefs;    /* list of band references */
+    char **semantic_labels;    /* list of semantic labels */
     int nsigs;          /* signature count */
     char title[100];    /* not used? */
     struct One_Sig *sig;    /* array of one signature per class */
@@ -102,7 +102,7 @@ struct ClassSig
 struct SigSet
 {
     int nbands;
-    char **bandrefs;    /* list of band references [nbands]char* */
+    char **semantic_labels;    /* list of semantic labels [nbands]char* */
     int nclasses;       /* ClassSig item count */
     char *title;
     struct ClassSig *ClassSig;

+ 1 - 1
lib/imagery/iclass_signatures.c

@@ -50,7 +50,7 @@ int I_iclass_init_signatures(struct Signature *sigs, struct Ref *refer)
 
     I_init_signatures(sigs, refer->nfiles);
     for (unsigned int i = refer->nfiles; i--;) {
-        sigs->bandrefs[i] = Rast_get_bandref_or_name(refer->file[i].name, refer->file[i].mapset);
+        sigs->semantic_labels[i] = Rast_get_semantic_label_or_name(refer->file[i].name, refer->file[i].mapset);
     }
 
     return 1;

+ 50 - 50
lib/imagery/sig.c

@@ -14,9 +14,9 @@
 int I_init_signatures(struct Signature *S, int nbands)
 {
     S->nbands = nbands;
-    S->bandrefs = (char **)G_malloc(nbands * sizeof(char **));
+    S->semantic_labels = (char **)G_malloc(nbands * sizeof(char **));
     for (int i = 0; i < nbands; i++)
-        S->bandrefs[i] = NULL;
+        S->semantic_labels[i] = NULL;
     S->nsigs = 0;
     S->sig = NULL;
     S->title[0] = 0;
@@ -69,11 +69,11 @@ int I_free_signatures(struct Signature *S)
     }
     free(S->sig);
     for (n = 0; n < S->nbands; n++)
-        free(S->bandrefs[n]);
-    free(S->bandrefs);
+        free(S->semantic_labels[n]);
+    free(S->semantic_labels);
 
     S->sig = NULL;
-    S->bandrefs = NULL;
+    S->semantic_labels = NULL;
     S->nbands = 0;
     S->nsigs = 0;
     S->title[0] = '\0';
@@ -142,7 +142,7 @@ int I_read_signatures(FILE * fd, struct Signature *S)
 {
     int ver, n, pos;
     char c, prev;
-    char bandref[GNAME_MAX];
+    char semantic_label[GNAME_MAX];
 
     I_init_signatures(S, 0);
     S->title[0] = 0;
@@ -164,37 +164,37 @@ int I_read_signatures(FILE * fd, struct Signature *S)
     I_get_to_eol(S->title, sizeof(S->title), fd);
     G_strip(S->title);
 
-    /* Read band references and count them to set nbands */
+    /* Read semantic labels and count them to set nbands */
     n = 0;
     pos = 0;
-    S->bandrefs = (char **)G_realloc(S->bandrefs, (n + 1) * sizeof(char **));
+    S->semantic_labels = (char **)G_realloc(S->semantic_labels, (n + 1) * sizeof(char **));
     while ((c = (char)fgetc(fd)) != EOF) {
         if (c == '\n') {
             if (prev != ' ') {
-                bandref[pos] = '\0';
-                S->bandrefs[n] = G_store(bandref);
+                semantic_label[pos] = '\0';
+                S->semantic_labels[n] = G_store(semantic_label);
                 n++;
             }
             S->nbands = n;
             break;
         }
         if (c == ' ') {
-            bandref[pos] = '\0';
-            S->bandrefs[n] = G_store(bandref);
+            semantic_label[pos] = '\0';
+            S->semantic_labels[n] = G_store(semantic_label);
             n++;
             /* [n] is 0 based thus: (n + 1) */
-            S->bandrefs = (char **)G_realloc(S->bandrefs, (n + 1) * sizeof(char **));
+            S->semantic_labels = (char **)G_realloc(S->semantic_labels, (n + 1) * sizeof(char **));
             pos = 0;
             prev = c;
             continue;
         }
-        /* Band references are limited to GNAME_MAX - 1 + \0 in length;
+        /* Semantic labels are limited to GNAME_MAX - 1 + \0 in length;
          * n is 0-based */
         if (pos == (GNAME_MAX - 2)) {
-            G_warning(_("Invalid signature file: band reference length limit exceeded"));
+            G_warning(_("Invalid signature file: semantic label length limit exceeded"));
             return -1;
         }
-        bandref[pos] = c;
+        semantic_label[pos] = c;
         pos++;
         prev = c;
     }
@@ -238,10 +238,10 @@ int I_write_signatures(FILE * fd, struct Signature *S)
     fprintf(fd, "1\n");
     /* Title of signatures */
     fprintf(fd, "#%s\n", S->title);
-    /* A list of space separated band references for each
+    /* A list of space separated semantic labels for each
      * raster map used to generate sigs. */
     for (k = 0; k < S->nbands; k++) {
-        fprintf(fd, "%s ", S->bandrefs[k]);
+        fprintf(fd, "%s ", S->semantic_labels[k]);
     }
     fprintf(fd, "\n");
     /* A signature for each target class */
@@ -253,7 +253,7 @@ int I_write_signatures(FILE * fd, struct Signature *S)
     fprintf(fd, "#%s\n", s->desc);
     /* Point count used to generate signature */
 	fprintf(fd, "%d\n", s->npoints);
-    /* Values are in the same order as band references */
+    /* Values are in the same order as semantic labels */
 	for (i = 0; i < S->nbands; i++)
 	    fprintf(fd, "%g ", s->mean[i]);
 	fprintf(fd, "\n");
@@ -271,21 +271,21 @@ int I_write_signatures(FILE * fd, struct Signature *S)
 /*!
  * \brief Reorder struct Signature to match imagery group member order
  *
- * The function will check for band reference match between signature struct
+ * The function will check for semantic label match between signature struct
  * and imagery group.
  *
- * In the case of a complete band reference match, values of passed in
+ * In the case of a complete semantic label match, values of passed in
  * struct Signature are reordered to match the order of imagery group items.
  *
- * If all band references are not identical (in
+ * If all semantic labels are not identical (in
  * arbitrary order), function will return two dimensional array with
  * comma separated list of:
- *      - [0] band references present in the signature struct but
+ *      - [0] semantic labels present in the signature struct but
  * absent in the imagery group
- *      - [1] band references present in the imagery group but
+ *      - [1] semantic labels present in the imagery group but
  * absent in the signature struct
  *
- * If no mismatch of band references for signatures or imagery group are
+ * If no mismatch of simantic labels for signatures or imagery group are
  * detected (== all are present in the other list), a NULL value will be
  * returned in the particular list of mismatches (not an empty string).
  * For example:
@@ -297,21 +297,21 @@ int I_write_signatures(FILE * fd, struct Signature *S)
  * \return NULL successfully sorted
  * \return err_array two comma separated lists of mismatches
  */
-char **I_sort_signatures_by_bandref(struct Signature *S, const struct Ref *R) {
+char **I_sort_signatures_by_semantic_label(struct Signature *S, const struct Ref *R) {
     unsigned int total, complete;
     unsigned int *match1, *match2, mc1, mc2, *new_order;
     double **new_means, ***new_vars;
-    char **group_bandrefs, **mismatches, **new_bandrefs;
+    char **group_semantic_labels, **mismatches, **new_semantic_labels;
 
     /* Safety measure. Untranslated as this should not happen in production! */
     if (S->nbands < 1 || R->nfiles < 1)
         G_fatal_error("Programming error. Invalid length structs passed to "
-                      "I_sort_signatures_by_bandref(%d, %d);", S->nbands,  R->nfiles);
+                      "I_sort_signatures_by_semantic_label(%d, %d);", S->nbands,  R->nfiles);
 
-    /* Obtain group band references */
-    group_bandrefs = (char **)G_malloc(R->nfiles * sizeof(char *));
+    /* Obtain group semantic labels */
+    group_semantic_labels = (char **)G_malloc(R->nfiles * sizeof(char *));
     for (unsigned int j = R->nfiles; j--;) {
-        group_bandrefs[j] = Rast_get_bandref_or_name(R->file[j].name, R->file[j].mapset);
+        group_semantic_labels[j] = Rast_get_semantic_label_or_name(R->file[j].name, R->file[j].mapset);
     }
 
     /* If lengths are not equal, there will be a mismatch */
@@ -323,7 +323,7 @@ char **I_sort_signatures_by_bandref(struct Signature *S, const struct Ref *R) {
     match2 = (unsigned int *)G_calloc(R->nfiles, sizeof(unsigned int));
 
     /* Allocate memory for temporary storage of sorted values */
-    new_bandrefs = (char **)G_malloc(S->nbands * sizeof(char *));
+    new_semantic_labels = (char **)G_malloc(S->nbands * sizeof(char *));
     new_means = (double **)G_malloc(S->nsigs * sizeof(double *));
     // new_vars[S.sig[x]][band1][band1]
     new_vars = (double ***)G_malloc(S->nsigs * sizeof(double **));
@@ -337,11 +337,11 @@ char **I_sort_signatures_by_bandref(struct Signature *S, const struct Ref *R) {
     /* Obtain order of matching items */
     for (unsigned int j = R->nfiles; j--;) {
         for (unsigned int i = S->nbands; i--;) {
-            if (S->bandrefs[i] && group_bandrefs[j] &&
-                !strcmp(S->bandrefs[i], group_bandrefs[j])) {
+            if (S->semantic_labels[i] && group_semantic_labels[j] &&
+                !strcmp(S->semantic_labels[i], group_semantic_labels[j])) {
                     if (complete) {
                         /* Reorder pointers to existing strings only */
-                        new_bandrefs[j] = S->bandrefs[i];
+                        new_semantic_labels[j] = S->semantic_labels[i];
                         new_order[i] = j;
                     }
                     /* Keep a track of matching items for error reporting */
@@ -352,7 +352,7 @@ char **I_sort_signatures_by_bandref(struct Signature *S, const struct Ref *R) {
         }
     }
 
-    /* Check for band reference mismatch */
+    /* Check for semantic label mismatch */
     mc1 = mc2 = 0;
     mismatches = (char **)G_malloc(2 * sizeof(char **));
     mismatches[0] = NULL;
@@ -360,8 +360,8 @@ char **I_sort_signatures_by_bandref(struct Signature *S, const struct Ref *R) {
     total = 1;
     for (unsigned int i = 0; i < S->nbands; i++) {
         if (!match1[i]) {
-            if (S->bandrefs[i])
-                total = total + strlen(S->bandrefs[i]);
+            if (S->semantic_labels[i])
+                total = total + strlen(S->semantic_labels[i]);
             else
                 total = total + 24;
             mismatches[0] = (char *)G_realloc(mismatches[0], total * sizeof(char *));
@@ -369,10 +369,10 @@ char **I_sort_signatures_by_bandref(struct Signature *S, const struct Ref *R) {
                 strcat(mismatches[0], ",");
             else
                 mismatches[0][0] = '\0';
-            if (S->bandrefs[i])
-                strcat(mismatches[0], S->bandrefs[i]);
+            if (S->semantic_labels[i])
+                strcat(mismatches[0], S->semantic_labels[i]);
             else
-                strcat(mismatches[0], "<band reference missing>");
+                strcat(mismatches[0], "<semantic label missing>");
             mc1++;
             total = total + 1;
         }
@@ -380,8 +380,8 @@ char **I_sort_signatures_by_bandref(struct Signature *S, const struct Ref *R) {
     total = 1;
     for (unsigned int j = 0; j < R->nfiles; j++) {
         if (!match2[j]) {
-            if (group_bandrefs[j])
-                total = total + strlen(group_bandrefs[j]);
+            if (group_semantic_labels[j])
+                total = total + strlen(group_semantic_labels[j]);
             else
                 total = total + 24;
             mismatches[1] = (char *)G_realloc(mismatches[1], total * sizeof(char *));
@@ -389,10 +389,10 @@ char **I_sort_signatures_by_bandref(struct Signature *S, const struct Ref *R) {
                 strcat(mismatches[1], ",");
             else
                 mismatches[1][0] = '\0';
-            if (group_bandrefs[j])
-                strcat(mismatches[1], group_bandrefs[j]);
+            if (group_semantic_labels[j])
+                strcat(mismatches[1], group_semantic_labels[j]);
             else
-                strcat(mismatches[1], "<band reference missing>");
+                strcat(mismatches[1], "<semantic label missing>");
             mc2++;
             total = total + 1;
         }
@@ -415,7 +415,7 @@ char **I_sort_signatures_by_bandref(struct Signature *S, const struct Ref *R) {
         }
 
         /* Replace values in struct with ordered ones */
-        memcpy(S->bandrefs, new_bandrefs, S->nbands * sizeof(char **));
+        memcpy(S->semantic_labels, new_semantic_labels, S->nbands * sizeof(char **));
         for (unsigned int c = S->nsigs; c--;) {
             memcpy(S->sig[c].mean, new_means[c], S->nbands * sizeof(double));
             for (unsigned int i = S->nbands; i--;)
@@ -425,12 +425,12 @@ char **I_sort_signatures_by_bandref(struct Signature *S, const struct Ref *R) {
 
     /* Clean up */
     for (unsigned int j = R->nfiles; j--;)
-        free(group_bandrefs[j]);
-    free(group_bandrefs);
+        free(group_semantic_labels[j]);
+    free(group_semantic_labels);
     free(new_order);
     free(match1);
     free(match2);
-    free(new_bandrefs);
+    free(new_semantic_labels);
     for (unsigned int c = S->nsigs; c--;) {
         free(new_means[c]);
         for (unsigned int i = S->nbands; i--;)

+ 53 - 53
lib/imagery/sigset.c

@@ -5,7 +5,7 @@
 #include <grass/imagery.h>
 
 static int gettag(FILE *, char *);
-static int get_bandrefs(FILE *, struct SigSet *);
+static int get_semantic_labels(FILE *, struct SigSet *);
 static int get_title(FILE *, struct SigSet *);
 static int get_class(FILE *, struct SigSet *);
 static int get_classnum(FILE *, struct ClassSig *);
@@ -65,9 +65,9 @@ struct ClassData *I_AllocClassData(struct SigSet *S,
 int I_InitSigSet(struct SigSet *S, int nbands)
 {
     S->nbands = nbands;
-    S->bandrefs = (char **)G_malloc(nbands * sizeof(char **));
+    S->semantic_labels = (char **)G_malloc(nbands * sizeof(char **));
     for (int i = 0; i < nbands; i++)
-        S->bandrefs[i] = NULL;
+        S->semantic_labels[i] = NULL;
     S->nclasses = 0;
     S->ClassSig = NULL;
     S->title = NULL;
@@ -160,8 +160,8 @@ int I_ReadSigSet(FILE * fd, struct SigSet *S)
         if (eq(tag, "title:"))
             if (get_title(fd, S) != 0)
                 return -1;
-        if (eq(tag, "bandrefs:"))
-            if (get_bandrefs(fd, S) != 0)
+        if (eq(tag, "semantic_labels:"))
+            if (get_semantic_labels(fd, S) != 0)
                 return -1;
         if (eq(tag, "class:"))
             if (get_class(fd, S) != 0)
@@ -178,22 +178,22 @@ static int gettag(FILE * fd, char *tag)
     return 1;
 }
 
-static int get_bandrefs(FILE * fd, struct SigSet *S)
+static int get_semantic_labels(FILE * fd, struct SigSet *S)
 {
     int n, pos;
     char c, prev;
-    char bandref[GNAME_MAX];
+    char semantic_label[GNAME_MAX];
 
-    /* Read band references and count them to set nbands */
+    /* Read semantic labels and count them to set nbands */
     n = 0;
     pos = 0;
-    S->bandrefs = (char **)G_realloc(S->bandrefs, (n + 1) * sizeof(char **));
+    S->semantic_labels = (char **)G_realloc(S->semantic_labels, (n + 1) * sizeof(char **));
     while ((c = (char)fgetc(fd)) != EOF) {
         if (c == '\n') {
             if (prev != ' ') {
-                bandref[pos] = '\0';
-                if (strlen(bandref) > 0) {
-                    S->bandrefs[n] = G_store(bandref);
+                semantic_label[pos] = '\0';
+                if (strlen(semantic_label) > 0) {
+                    S->semantic_labels[n] = G_store(semantic_label);
                     n++;
                 }
             }
@@ -201,26 +201,26 @@ static int get_bandrefs(FILE * fd, struct SigSet *S)
             break;
         }
         if (c == ' ') {
-            bandref[pos] = '\0';
-            if (strlen(bandref) > 0) {
-                S->bandrefs[n] = G_store(bandref);
+            semantic_label[pos] = '\0';
+            if (strlen(semantic_label) > 0) {
+                S->semantic_labels[n] = G_store(semantic_label);
                 n++;
                 /* [n] is 0 based thus: (n + 1) */
-                S->bandrefs =
-                    (char **)G_realloc(S->bandrefs,
+                S->semantic_labels =
+                    (char **)G_realloc(S->semantic_labels,
                                        (n + 1) * sizeof(char **));
             }
             pos = 0;
             prev = c;
             continue;
         }
-        /* Band references are limited to GNAME_MAX - 1 + \0 in length;
+        /* Semantic labels are limited to GNAME_MAX - 1 + \0 in length;
          * n is 0-based */
         if (pos == (GNAME_MAX - 2)) {
-            G_warning(_("Invalid signature file: band reference length limit exceeded"));
+            G_warning(_("Invalid signature file: semantic label length limit exceeded"));
             return -1;
         }
-        bandref[pos] = c;
+        semantic_label[pos] = c;
         pos++;
         prev = c;
     }
@@ -402,9 +402,9 @@ int I_WriteSigSet(FILE * fd, const struct SigSet *S)
     /* This is version 1 sigset file format */
     fprintf(fd, "1\n");
     fprintf(fd, "title: %s\n", I_GetSigTitle(S));
-    fprintf(fd, "bandrefs: ");
+    fprintf(fd, "semantic_labels: ");
     for (i = 0; i < S->nbands; i++) {
-        fprintf(fd, "%s ", S->bandrefs[i]);
+        fprintf(fd, "%s ", S->semantic_labels[i]);
     }
     fprintf(fd, "\n");
     for (i = 0; i < S->nclasses; i++) {
@@ -444,23 +444,23 @@ int I_WriteSigSet(FILE * fd, const struct SigSet *S)
 /*!
  * \brief Reorder struct SigSet to match imagery group member order
  *
- * The function will check for band reference match between sigset struct
+ * The function will check for semantic label match between sigset struct
  * and imagery group.
  *
- * In the case of a complete band reference match, values of passed in
+ * In the case of a complete semantic label match, values of passed in
  * struct SigSet are reordered to match the order of imagery group items.
  * This reordering is done only for items present in the sigset file.
  * Thus reordering should be done only after calling I_ReadSigSet.
  *
- * If all band references are not identical (in
+ * If all semantic labels are not identical (in
  * arbitrary order), function will return two dimensional array with
  * comma separated list of:
- *      - [0] band references present in the signature struct but
+ *      - [0] semantic labels present in the signature struct but
  * absent in the imagery group
- *      - [1] band references present in the imagery group but
+ *      - [1] semantic labels present in the imagery group but
  * absent in the signature struct
  *
- * If no mismatch of band references for signatures or imagery group are
+ * If no mismatch of semantic labels for signatures or imagery group are
  * detected (== all are present in the other list), a NULL value will be
  * returned in the particular list of mismatches (not an empty string).
  * For example:
@@ -472,23 +472,23 @@ int I_WriteSigSet(FILE * fd, const struct SigSet *S)
  * \return NULL successfully sorted
  * \return err_array two comma separated lists of mismatches
  */
-char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R)
+char **I_SortSigSetBySemanticLabel(struct SigSet *S, const struct Ref *R)
 {
     unsigned int total, complete;
     unsigned int *match1, *match2, mc1, mc2, *new_order;
     double ***new_means, ****new_vars;
-    char **group_bandrefs, **mismatches, **new_bandrefs;
+    char **group_semantic_labels, **mismatches, **new_semantic_labels;
 
     /* Safety measure. Untranslated as this should not happen in production! */
     if (S->nbands < 1 || R->nfiles < 1)
         G_fatal_error("Programming error. Invalid length structs passed to "
-                      "I_sort_signatures_by_bandref(%d, %d);", S->nbands,
+                      "I_sort_signatures_by_semantic_label(%d, %d);", S->nbands,
                       R->nfiles);
 
-    /* Obtain group band references */
-    group_bandrefs = (char **)G_malloc(R->nfiles * sizeof(char *));
+    /* Obtain group semantic labels */
+    group_semantic_labels = (char **)G_malloc(R->nfiles * sizeof(char *));
     for (unsigned int j = R->nfiles; j--;) {
-        group_bandrefs[j] = Rast_get_bandref_or_name(R->file[j].name, R->file[j].mapset);
+        group_semantic_labels[j] = Rast_get_semantic_label_or_name(R->file[j].name, R->file[j].mapset);
     }
 
     /* If lengths are not equal, there will be a mismatch */
@@ -500,7 +500,7 @@ char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R)
     match2 = (unsigned int *)G_calloc(R->nfiles, sizeof(unsigned int));
 
     /* Allocate memory for temporary storage of sorted values */
-    new_bandrefs = (char **)G_malloc(S->nbands * sizeof(char *));
+    new_semantic_labels = (char **)G_malloc(S->nbands * sizeof(char *));
     new_means = (double ***)G_malloc(S->nclasses * sizeof(double **));
     // new_vars[S.ClassSig[x]][.SubSig[y]][R[band1]][R[band1]]
     new_vars = (double ****)G_malloc(S->nclasses * sizeof(double ***));
@@ -524,11 +524,11 @@ char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R)
     /* Obtain order of matching items */
     for (unsigned int j = R->nfiles; j--;) {
         for (unsigned int i = S->nbands; i--;) {
-            if (S->bandrefs[i] && group_bandrefs[j] &&
-                !strcmp(S->bandrefs[i], group_bandrefs[j])) {
+            if (S->semantic_labels[i] && group_semantic_labels[j] &&
+                !strcmp(S->semantic_labels[i], group_semantic_labels[j])) {
                 if (complete) {
                     /* Reorder pointers to existing strings only */
-                    new_bandrefs[j] = S->bandrefs[i];
+                    new_semantic_labels[j] = S->semantic_labels[i];
                     new_order[i] = j;
                 }
                 /* Keep a track of matching items for error reporting */
@@ -539,7 +539,7 @@ char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R)
         }
     }
 
-    /* Check for band reference mismatch */
+    /* Check for semantic label mismatch */
     mc1 = mc2 = 0;
     mismatches = (char **)G_malloc(2 * sizeof(char **));
     mismatches[0] = NULL;
@@ -547,8 +547,8 @@ char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R)
     total = 1;
     for (unsigned int i = 0; i < S->nbands; i++) {
         if (!match1[i]) {
-            if (S->bandrefs[i])
-                total = total + strlen(S->bandrefs[i]);
+            if (S->semantic_labels[i])
+                total = total + strlen(S->semantic_labels[i]);
             else
                 total = total + 24;
             mismatches[0] =
@@ -557,10 +557,10 @@ char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R)
                 strcat(mismatches[0], ",");
             else
                 mismatches[0][0] = '\0';
-            if (S->bandrefs[i])
-                strcat(mismatches[0], S->bandrefs[i]);
+            if (S->semantic_labels[i])
+                strcat(mismatches[0], S->semantic_labels[i]);
             else
-                strcat(mismatches[0], "<band reference missing>");
+                strcat(mismatches[0], "<semantic label missing>");
             mc1++;
             total = total + 1;
         }
@@ -568,8 +568,8 @@ char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R)
     total = 1;
     for (unsigned int j = 0; j < R->nfiles; j++) {
         if (!match2[j]) {
-            if (group_bandrefs[j])
-                total = total + strlen(group_bandrefs[j]);
+            if (group_semantic_labels[j])
+                total = total + strlen(group_semantic_labels[j]);
             else
                 total = total + 24;
             mismatches[1] =
@@ -578,10 +578,10 @@ char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R)
                 strcat(mismatches[1], ",");
             else
                 mismatches[1][0] = '\0';
-            if (group_bandrefs[j])
-                strcat(mismatches[1], group_bandrefs[j]);
+            if (group_semantic_labels[j])
+                strcat(mismatches[1], group_semantic_labels[j]);
             else
-                strcat(mismatches[1], "<band reference missing>");
+                strcat(mismatches[1], "<semantic label missing>");
             mc2++;
             total = total + 1;
         }
@@ -603,7 +603,7 @@ char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R)
         }
 
         /* Replace values in struct with ordered ones */
-        memcpy(S->bandrefs, new_bandrefs, S->nbands * sizeof(char **));
+        memcpy(S->semantic_labels, new_semantic_labels, S->nbands * sizeof(char **));
         for (unsigned int c = S->nclasses; c--;) {
             for (unsigned int s = S->ClassSig[c].nsubclasses; s--;) {
                 memcpy(S->ClassSig[c].SubSig[s].means, new_means[c][s],
@@ -617,12 +617,12 @@ char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R)
 
     /* Clean up */
     for (unsigned int j = R->nfiles; j--;)
-        free(group_bandrefs[j]);
-    free(group_bandrefs);
+        free(group_semantic_labels[j]);
+    free(group_semantic_labels);
     free(new_order);
     free(match1);
     free(match2);
-    free(new_bandrefs);
+    free(new_semantic_labels);
     for (unsigned int c = S->nclasses; c--;) {
         for (unsigned int s = S->ClassSig[c].nsubclasses; s--;) {
             free(new_means[c][s]);

+ 98 - 76
lib/imagery/testsuite/test_imagery_sigfile.py

@@ -21,7 +21,7 @@ from grass.pygrass import utils
 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 @@ from grass.lib.imagery import (
     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 @@ class SignatureFileTestCase(TestCase):
         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 @@ class SignatureFileTestCase(TestCase):
 
         # 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 @@ class SignatureFileTestCase(TestCase):
         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 @@ class SignatureFileTestCase(TestCase):
         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 @@ class SignatureFileTestCase(TestCase):
 
     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 @@ class SignatureFileTestCase(TestCase):
         # 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 @@ class SignatureFileTestCase(TestCase):
         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 @@ class SignatureFileTestCase(TestCase):
 
         # 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 @@ class SignatureFileTestCase(TestCase):
         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 @@ class SignatureFileTestCase(TestCase):
         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 @@ class SignatureFileTestCase(TestCase):
         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 @@ class SortSignaturesByBandrefTest(TestCase):
         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 @@ class SortSignaturesByBandrefTest(TestCase):
         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 @@ class SortSignaturesByBandrefTest(TestCase):
         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 @@ class SortSignaturesByBandrefTest(TestCase):
         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 @@ class SortSignaturesByBandrefTest(TestCase):
         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 @@ class SortSignaturesByBandrefTest(TestCase):
         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 @@ class SortSignaturesByBandrefTest(TestCase):
                 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 @@ class SortSignaturesByBandrefTest(TestCase):
         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 @@ class SortSignaturesByBandrefTest(TestCase):
         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,
-            "<band reference missing>,<band reference missing>,"
-            + "<band reference missing>,<band reference missing>,"
-            + "<band reference missing>,<band reference missing>,"
-            + "<band reference missing>,<band reference missing>,"
-            + "<band reference missing>",
+            "<semantic label missing>,<semantic label missing>,"
+            + "<semantic label missing>,<semantic label missing>,"
+            + "<semantic label missing>,<semantic label missing>,"
+            + "<semantic label missing>,<semantic label missing>,"
+            + "<semantic label missing>",
         )
         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 @@ class SortSignaturesByBandrefTest(TestCase):
         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 @@ class SortSignaturesByBandrefTest(TestCase):
         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 @@ class SortSignaturesByBandrefTest(TestCase):
         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 @@ class SortSignaturesByBandrefTest(TestCase):
         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 @@ class SortSignaturesByBandrefTest(TestCase):
         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 @@ class SortSignaturesByBandrefTest(TestCase):
         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 @@ class SortSignaturesByBandrefTest(TestCase):
         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 @@ class SortSignaturesByBandrefTest(TestCase):
         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 @@ class SortSignaturesByBandrefTest(TestCase):
         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 @@ class SortSignaturesByBandrefTest(TestCase):
         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:

+ 71 - 55
lib/imagery/testsuite/test_imagery_sigsetfile.py

@@ -21,7 +21,7 @@ from grass.pygrass import utils
 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 @@ from grass.lib.imagery import (
     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 @@ class SigSetFileTestCase(TestCase):
         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 @@ class SigSetFileTestCase(TestCase):
 
         # 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 @@ class SigSetFileTestCase(TestCase):
         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_labels[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 @@ class SigSetFileTestCase(TestCase):
 
         # 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 @@ class SigSetFileTestCase(TestCase):
 
         # 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 @@ class SigSetFileTestCase(TestCase):
 
         # 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 @@ class SigSetFileTestCase(TestCase):
 
         # 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 @@ class SigSetFileTestCase(TestCase):
         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_labels[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 @@ class SigSetFileTestCase(TestCase):
         # 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 @@ class SortSigSetByBandrefTest(TestCase):
         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 @@ class SortSigSetByBandrefTest(TestCase):
         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 @@ class SortSigSetByBandrefTest(TestCase):
         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 @@ class SortSigSetByBandrefTest(TestCase):
         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 @@ class SortSigSetByBandrefTest(TestCase):
                 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 @@ class SortSigSetByBandrefTest(TestCase):
         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 @@ class SortSigSetByBandrefTest(TestCase):
         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,
-            "<band reference missing>,<band reference missing>,"
-            + "<band reference missing>,<band reference missing>,"
-            + "<band reference missing>,<band reference missing>,"
-            + "<band reference missing>,<band reference missing>,"
-            + "<band reference missing>",
+            "<semantic label missing>,<semantic label missing>,"
+            + "<semantic label missing>,<semantic label missing>,"
+            + "<semantic label missing>,<semantic label missing>,"
+            + "<semantic label missing>,<semantic label missing>,"
+            + "<semantic label missing>",
         )
         self.assertEqual(ref_err, f"The_Doors,{self.map3}")
 
@@ -395,7 +401,7 @@ class SortSigSetByBandrefTest(TestCase):
         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 @@ class SortSigSetByBandrefTest(TestCase):
         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 @@ class SortSigSetByBandrefTest(TestCase):
         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 @@ class SortSigSetByBandrefTest(TestCase):
         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_SortSigSetBySemanticLabel(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.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 @@ class SortSigSetByBandrefTest(TestCase):
         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 @@ class SortSigSetByBandrefTest(TestCase):
         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_SortSigSetBySemanticLabel(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.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)

+ 31 - 31
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 <shortcut>_<bandname>.
- * 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++;

+ 38 - 38
lib/raster/testsuite/test_raster_metadata.py

@@ -20,61 +20,61 @@ from grass.pygrass import utils
 
 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 @@ class RastBandReferenceTestCase(TestCase):
         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__":

+ 1 - 1
lib/temporal/SQL/raster_metadata_table.sql

@@ -19,7 +19,7 @@ CREATE TABLE  raster_metadata (
   ewres DOUBLE PRECISION NOT NULL,
   min DOUBLE PRECISION,
   max DOUBLE PRECISION,
-  band_reference VARCHAR,
+  semantic_label VARCHAR,
   PRIMARY KEY (id)
 );
 

+ 2 - 2
lib/temporal/SQL/raster_views.sql

@@ -16,7 +16,7 @@ CREATE VIEW raster_view_abs_time AS SELECT
             A3.north, A3.south, A3.east, A3.west, A3.bottom, A3.top, A3.proj,
             A4.datatype, A4.cols, A4.rows,
             A4.nsres, A4.ewres, A4.min, A4.max,
-            A4.number_of_cells, A4.band_reference, A5.registered_stds
+            A4.number_of_cells, A4.semantic_label, A5.registered_stds
             FROM raster_base A1, raster_absolute_time A2, 
             raster_spatial_extent A3, raster_metadata A4,
             raster_stds_register A5
@@ -32,7 +32,7 @@ CREATE VIEW raster_view_rel_time AS SELECT
             A3.north, A3.south, A3.east, A3.west, A3.bottom, A3.top, A3.proj,
             A4.datatype, A4.cols, A4.rows,
             A4.nsres, A4.ewres, A4.min, A4.max,
-            A4.number_of_cells, A4.band_reference, A5.registered_stds
+            A4.number_of_cells, A4.semantic_label, A5.registered_stds
             FROM raster_base A1, raster_relative_time A2, 
             raster_spatial_extent A3, raster_metadata A4,
             raster_stds_register A5

+ 1 - 1
lib/temporal/SQL/update_strds_metadata_template.sql

@@ -43,7 +43,7 @@ UPDATE strds_metadata SET ewres_max =
        ) WHERE id = 'SPACETIME_ID';
 -- Update the number of registered bands
 UPDATE strds_metadata SET number_of_bands =
-       (SELECT count(distinct band_reference) FROM raster_metadata WHERE
+       (SELECT count(distinct semantic_label) FROM raster_metadata WHERE
        raster_metadata.id IN
     		(SELECT id FROM SPACETIME_REGISTER_TABLE)
        ) WHERE id = 'SPACETIME_ID';

+ 1 - 1
lib/temporal/SQL/upgrade_db_2_to_3.sql

@@ -6,7 +6,7 @@
 
 -- raster_metadata_table.sql
 ALTER TABLE raster_metadata
- ADD COLUMN band_reference VARCHAR;
+ ADD COLUMN semantic_label VARCHAR;
 
 -- strds_metadata_table.sql
 ALTER TABLE strds_metadata

+ 1 - 1
python/grass/Makefile

@@ -7,7 +7,6 @@ PYDIR = $(ETC)/python/grass
 
 SUBDIRS = \
 	app \
-	bandref \
 	benchmark \
 	exceptions \
 	grassdb \
@@ -17,6 +16,7 @@ SUBDIRS = \
 	pydispatch \
 	pygrass \
 	script \
+	semantic_label \
 	temporal \
 	utils
 

+ 0 - 1
python/grass/bandref/__init__.py

@@ -1 +0,0 @@
-from .reader import BandReferenceReader, BandReferenceReaderError

+ 15 - 15
python/grass/pygrass/raster/abstract.py

@@ -162,31 +162,31 @@ class Info(object):
     def mtype(self):
         return RTYPE_STR[libraster.Rast_map_type(self.name, self.mapset)]
 
-    def _get_bandref(self):
-        """Get band reference identifier.
+    def _get_semantic_label(self):
+        """Get semantic label identifier.
 
-        :return str: band identifier (eg. S2_1) or None
+        :return str: semantic label (eg. S2_1) or None
         """
 
-        bandref = libraster.Rast_read_bandref(self.name, self.mapset)
-        if bandref:
-            return utils.decode(bandref)
+        semantic_label = libraster.Rast_read_semantic_label(self.name, self.mapset)
+        if semantic_label:
+            return utils.decode(semantic_label)
         return None
 
     @must_be_in_current_mapset
-    def _set_bandref(self, bandref):
-        """Set/Unset band reference identifier.
+    def _set_semantic_label(self, semantic_label):
+        """Set/Unset semantic label identifier.
 
-        :param str bandref: band reference to assign or None to remove (unset)
+        :param str semantic_label: semantic label to assign or None to remove (unset)
         """
-        if bandref:
-            if libraster.Rast_legal_bandref(bandref) is False:
-                raise ValueError(_("Invalid band reference"))
-            libraster.Rast_write_bandref(self.name, bandref)
+        if semantic_label:
+            if libraster.Rast_legal_semantic_label(semantic_label) is False:
+                raise ValueError(_("Invalid semantic label"))
+            libraster.Rast_write_semantic_label(self.name, semantic_label)
         else:
-            libgis.G_remove_misc("cell_misc", "bandref", self.name)
+            libgis.G_remove_misc("cell_misc", "semantic_label", self.name)
 
-    bandref = property(_get_bandref, _set_bandref)
+    semantic_label = property(_get_semantic_label, _set_semantic_label)
 
     def _get_units(self):
         units = libraster.Rast_read_units(self.name, self.mapset)

+ 1 - 1
python/grass/bandref/Makefile

@@ -5,7 +5,7 @@ include $(MODULE_TOPDIR)/include/Make/Python.make
 
 PYDIR = $(ETC)/python
 GDIR = $(PYDIR)/grass
-DSTDIR = $(GDIR)/bandref
+DSTDIR = $(GDIR)/semantic_label
 
 MODULES = reader
 

+ 1 - 0
python/grass/semantic_label/__init__.py

@@ -0,0 +1 @@
+from .reader import SemanticLabelReader, SemanticLabelReaderError

+ 55 - 51
python/grass/bandref/reader.py

@@ -5,29 +5,28 @@ import glob
 import re
 from collections import OrderedDict
 
+import grass.script as gs
 
-# band reference should be required to have the format
-# <shortcut>_<band>
-# instead, the sensor name should be stored somewhere else,
-# and band names should be STAC common names, see
+# Semantic label can have any form. Explanatory metadata can be stored
+# separately. It is suggested to follow some standard e.g. remote
+# sensing band names should be STAC common names, see
 # https://stacspec.org/
 # https://github.com/radiantearth/stac-spec/blob/master/extensions/eo/README.md#band-object
-# custom names must be possible
 
 
-class BandReferenceReaderError(Exception):
+class SemanticLabelReaderError(Exception):
     pass
 
 
-class BandReferenceReader:
-    """Band references reader"""
+class SemanticLabelReader:
+    """Semantic label reader"""
 
     def __init__(self):
         self._json_files = glob.glob(
             os.path.join(os.environ["GISBASE"], "etc", "g.bands", "*.json")
         )
         if not self._json_files:
-            raise BandReferenceReaderError("No band definitions found")
+            raise SemanticLabelReaderError("No semantic label definitions found")
 
         self._read_config()
 
@@ -39,7 +38,7 @@ class BandReferenceReader:
                 with open(json_file) as fd:
                     config = json.load(fd, object_pairs_hook=OrderedDict)
             except json.decoder.JSONDecodeError as e:
-                raise BandReferenceReaderError(
+                raise SemanticLabelReaderError(
                     "Unable to parse '{}': {}".format(json_file, e)
                 )
 
@@ -59,19 +58,19 @@ class BandReferenceReader:
         for items in config.values():
             for item in ("shortcut", "bands"):
                 if item not in items.keys():
-                    raise BandReferenceReaderError(
+                    raise SemanticLabelReaderError(
                         "Invalid band definition: <{}> is missing".format(item)
                     )
             if len(items["bands"]) < 1:
-                raise BandReferenceReaderError(
+                raise SemanticLabelReaderError(
                     "Invalid band definition: no bands defined"
                 )
 
     @staticmethod
-    def _print_band_extended(band, item):
-        """Print band-specific metadata
+    def _print_label_extended(label, item):
+        """Print label specific metadata
 
-        :param str band: band identifier
+        :param str label: label identifier
         :param str item: items to be printed out
         """
 
@@ -84,25 +83,32 @@ class BandReferenceReader:
                 print("{}{}: {}".format(" " * indent * 2, k, v))
 
         indent = 4
-        print("{}band: {}".format(" " * indent, band))
-        for k, v in item[band].items():
+        print("{}label: {}".format(" " * indent, label))
+        for k, v in item[label].items():
             print_kv(k, v, indent)
 
-    def _print_band(self, shortcut, band, tag=None):
-        sys.stdout.write(self._band_identifier(shortcut, band))
+    def _print_label(self, semantic_label=None, tag=None):
+        sys.stdout.write(semantic_label)
         if tag:
             sys.stdout.write(" {}".format(tag))
         sys.stdout.write(os.linesep)
 
-    def print_info(self, shortcut=None, band=None, extended=False):
-        """Prints band reference information to stdout.
+    def print_info(self, shortcut=None, band=None, semantic_label=None, extended=False):
+        """Prints semantic label information to stdout.
 
-        Can be filtered by shortcut or band identifier.
+        Can be filtered by semantic label identifier.
 
         :param str shortcut: shortcut to filter (eg. S2) or None
         :param str band: band (eg. 1) or None
+        :param str semantic_label: semantic_label filter (eg. S2_8A) or None
         :param bool extended: print also extended metadata
         """
+        if semantic_label:
+            try:
+                shortcut, band = semantic_label.split("_")
+            except ValueError:
+                shortcut = semantic_label
+                band = None
         found = False
         for root in self.config.values():
             for item in root.values():
@@ -110,11 +116,11 @@ class BandReferenceReader:
                     if shortcut and re.match(shortcut, item["shortcut"]) is None:
                         continue
                 except re.error as e:
-                    raise BandReferenceReaderError("Invalid pattern: {}".format(e))
+                    raise SemanticLabelReaderError("Invalid pattern: {}".format(e))
 
                 found = True
                 if band and band not in item["bands"]:
-                    raise BandReferenceReaderError(
+                    raise SemanticLabelReaderError(
                         "Band <{}> not found in <{}>".format(band, shortcut)
                     )
 
@@ -128,52 +134,54 @@ class BandReferenceReader:
 
                     # print detailed band information
                     if band:
-                        self._print_band_extended(band, item["bands"])
+                        self._print_label_extended(band, item["bands"])
                     else:
                         for iband in item["bands"]:
-                            self._print_band_extended(iband, item["bands"])
+                            self._print_label_extended(iband, item["bands"])
                 else:
                     # basic information only
                     if band:
-                        self._print_band(
-                            item["shortcut"], band, item["bands"][band].get("tag")
+                        self._print_label(
+                            semantic_label=item["shortcut"],
+                            tag=item["bands"][band].get("tag"),
                         )
                     else:
                         for iband in item["bands"]:
-                            self._print_band(
-                                item["shortcut"], iband, item["bands"][iband].get("tag")
+                            self._print_label(
+                                semantic_label=item["shortcut"],
+                                tag=item["bands"][iband].get("tag"),
                             )
 
-        # raise error when defined shortcut not found
-        if shortcut and not found:
-            raise BandReferenceReaderError(
-                "Band reference <{}> not found".format(shortcut)
+        # print warning when defined shortcut not found
+        if not found:
+            gs.warning(
+                "Metadata for semantic label <{}> not found".format(semantic_label)
             )
 
-    def find_file(self, band_reference):
-        """Find file by band reference.
+    def find_file(self, semantic_label):
+        """Find file by semantic label.
 
         Match is case-insensitive.
 
-        :param str band_reference: band reference identifier to search for (eg. S2_1)
+        :param str semantic_label: semantic label identifier to search for (eg. S2_1)
 
         :return str: file basename if found or None
         """
         try:
-            shortcut, band = band_reference.split("_")
+            shortcut, band = semantic_label.split("_")
         except ValueError:
-            # raise BandReferenceReaderError("Invalid band identifier <{}>".format(
-            #    band_reference
+            # raise SemanticLabelReaderError("Invalid band identifier <{}>".format(
+            #    semantic_label
             # ))
-            shortcut = "unknown"
-            band = band_reference
+            shortcut = None
 
         for filename, config in self.config.items():
             for root in config.keys():
-                if config[root][
-                    "shortcut"
-                ].upper() == shortcut.upper() and band.upper() in map(
-                    lambda x: x.upper(), config[root]["bands"].keys()
+                if (
+                    shortcut
+                    and config[root]["shortcut"].upper() == shortcut.upper()
+                    and band.upper()
+                    in map(lambda x: x.upper(), config[root]["bands"].keys())
                 ):
                     return filename
 
@@ -188,9 +196,5 @@ class BandReferenceReader:
         for root in self.config.values():
             for item in root.values():
                 for band in item["bands"]:
-                    bands.append(self._band_identifier(item["shortcut"], band))
+                    bands.append("{}_{}".format(item["shortcut"], band))
         return bands
-
-    @staticmethod
-    def _band_identifier(shortcut, band):
-        return "{}_{}".format(shortcut, band)

+ 4 - 4
python/grass/temporal/abstract_map_dataset.py

@@ -1158,7 +1158,7 @@ class AbstractMapDataset(AbstractDataset):
 
         return statement
 
-    def read_band_reference_from_grass(self):
+    def read_semantic_label_from_grass(self):
         """Read the band identifier of this map from the map metadata
         in the GRASS file system based spatial database and
         set the internal band identifier that should be insert/updated
@@ -1169,13 +1169,13 @@ class AbstractMapDataset(AbstractDataset):
         """
         pass
 
-    def set_band_reference(self, band_reference):
-        """Set band reference identifier
+    def set_semantic_label(self, semantic_label):
+        """Set semantic label identifier
 
         Currently only implemented in RasterDataset. Otherwise
         report a warning.
         """
-        self.msgr.warning(_("Band references can only be assigned to raster maps"))
+        self.msgr.warning(_("semantic labels can only be assigned to raster maps"))
 
 
 ###############################################################################

+ 21 - 21
python/grass/temporal/abstract_space_time_dataset.py

@@ -63,13 +63,13 @@ class AbstractSpaceTimeDataset(AbstractDataset):
         self.map_counter = 0
 
         # SpaceTimeRasterDataset related only
-        self.band_reference = None
+        self.semantic_label = None
 
-    def get_name(self, band_reference=True):
-        """Get dataset name including band reference filter if enabled.
+    def get_name(self, semantic_label=True):
+        """Get dataset name including semantic label filter if enabled.
 
-        :param bool band_reference: True to return dataset name
-        including band reference filter if defined
+        :param bool semantic_label: True to return dataset name
+        including semantic label filter if defined
         (eg. "landsat.L8_1") otherwise dataset name is returned only
         (eg. "landsat").
 
@@ -78,8 +78,8 @@ class AbstractSpaceTimeDataset(AbstractDataset):
         """
         dataset_name = super(AbstractSpaceTimeDataset, self).get_name()
 
-        if band_reference and self.band_reference:
-            return "{}.{}".format(dataset_name, self.band_reference)
+        if semantic_label and self.semantic_label:
+            return "{}.{}".format(dataset_name, self.semantic_label)
 
         return dataset_name
 
@@ -1520,10 +1520,10 @@ class AbstractSpaceTimeDataset(AbstractDataset):
 
         return obj_list
 
-    def _update_where_statement_by_band_reference(self, where):
-        """Update given SQL WHERE statement by band reference.
+    def _update_where_statement_by_semantic_label(self, where):
+        """Update given SQL WHERE statement by semantic label.
 
-        Call this method only when self.band_reference is defined.
+        Call this method only when self.semantic_label is defined.
 
         :param str where: SQL WHERE statement to be updated
 
@@ -1548,12 +1548,12 @@ class AbstractSpaceTimeDataset(AbstractDataset):
             where = ""
 
         # be case-insensitive
-        if "_" in self.band_reference:
-            # fully-qualified band reference
-            where += "band_reference IN ('{}'".format(self.band_reference.upper())
+        if "_" in self.semantic_label:
+            # fully-qualified semantic label
+            where += "semantic_label IN ('{}'".format(self.semantic_label.upper())
 
             # be zero-padding less sensitive
-            shortcut, identifier = self.band_reference.split("_", -1)
+            shortcut, identifier = self.semantic_label.split("_", -1)
             identifier_zp = leading_zero(identifier)
             if identifier_zp:
                 where += ", '{fl}_{zp}'".format(
@@ -1564,19 +1564,19 @@ class AbstractSpaceTimeDataset(AbstractDataset):
             where += ")"
         else:
             # shortcut or band identifier given
-            shortcut_identifier = leading_zero(self.band_reference)
+            shortcut_identifier = leading_zero(self.semantic_label)
             if shortcut_identifier:
                 where += (
                     "{br} LIKE '{si}\_%' {esc} OR {br} LIKE '%\_{si}' {esc} OR "
                     "{br} LIKE '{orig}\_%' {esc} OR {br} LIKE '%\_{orig}' {esc}".format(
-                        br="band_reference",
+                        br="semantic_label",
                         si=shortcut_identifier,
-                        orig=self.band_reference.upper(),
+                        orig=self.semantic_label.upper(),
                         esc="ESCAPE '\\'",
                     )
                 )
             else:
-                where += "band_reference = '{}'".format(self.band_reference)
+                where += "semantic_label = '{}'".format(self.semantic_label)
 
         return where
 
@@ -1622,9 +1622,9 @@ class AbstractSpaceTimeDataset(AbstractDataset):
                     self.get_map_register(),
                 )
 
-            # filter by band reference identifier
-            if self.band_reference:
-                where = self._update_where_statement_by_band_reference(where)
+            # filter by semantic label identifier
+            if self.semantic_label:
+                where = self._update_where_statement_by_semantic_label(where)
 
             if where is not None and where != "":
                 sql += " AND (%s)" % (where.split(";")[0])

+ 40 - 40
python/grass/temporal/c_libraries_interface.py

@@ -48,9 +48,9 @@ class RPCDefs(object):
     G_LOCATION = 12
     G_GISDBASE = 13
     READ_MAP_FULL_INFO = 14
-    WRITE_BAND_REFERENCE = 15
-    READ_BAND_REFERENCE = 16
-    REMOVE_BAND_REFERENCE = 17
+    WRITE_SEMANTIC_LABEL = 15
+    READ_SEMANTIC_LABEL = 16
+    REMOVE_SEMANTIC_LABEL = 17
     G_FATAL_ERROR = 49
 
     TYPE_RASTER = 0
@@ -525,12 +525,12 @@ def _remove_timestamp(lock, conn, data):
 ###############################################################################
 
 
-def _read_band_reference(lock, conn, data):
+def _read_semantic_label(lock, conn, data):
     """Read the file based GRASS band identifier
     the result using the provided pipe.
 
     The result to be sent via pipe is the return value of
-    Rast_read_bandref: either a band reference string or None.
+    Rast_read_semantic_label: either a semantic label string or None.
 
     :param lock: A multiprocessing.Lock instance
     :param conn: A multiprocessing.Pipe instance used to send True or False
@@ -538,7 +538,7 @@ def _read_band_reference(lock, conn, data):
                  mapset, layer, timestring]
 
     """
-    bandref = None
+    semantic_label = None
     try:
         maptype = data[1]
         name = data[2]
@@ -548,27 +548,27 @@ def _read_band_reference(lock, conn, data):
         if maptype == RPCDefs.TYPE_RASTER:
             # Must use temporary variable to work around
             # ValueError: ctypes objects containing pointers cannot be pickled
-            ret = libraster.Rast_read_bandref(name, mapset)
+            ret = libraster.Rast_read_semantic_label(name, mapset)
             if ret:
-                bandref = decode(ret)
+                semantic_label = decode(ret)
         else:
             logging.error(
-                "Unable to read band reference. " "Unsupported map type %s" % maptype
+                "Unable to read semantic label. " "Unsupported map type %s" % maptype
             )
             return -1
     except:
         raise
     finally:
-        conn.send(bandref)
+        conn.send(semantic_label)
 
 
 ###############################################################################
 
 
-def _write_band_reference(lock, conn, data):
+def _write_semantic_label(lock, conn, data):
     """Write the file based GRASS band identifier.
 
-    Rises ValueError on invalid band reference.
+    Rises ValueError on invalid semantic label.
     Always sends back True.
 
     :param lock: A multiprocessing.Lock instance
@@ -582,15 +582,15 @@ def _write_band_reference(lock, conn, data):
         name = data[2]
         # mapset = data[3]
         # layer = data[4]
-        bandref = data[5]
+        semantic_label = data[5]
 
         if maptype == RPCDefs.TYPE_RASTER:
-            if libraster.Rast_legal_bandref(bandref) is False:
-                raise ValueError(_("Invalid band reference"))
-            libraster.Rast_write_bandref(name, bandref)
+            if libraster.Rast_legal_semantic_label(semantic_label) is False:
+                raise ValueError(_("Invalid semantic label"))
+            libraster.Rast_write_semantic_label(name, semantic_label)
         else:
             logging.error(
-                "Unable to write band reference. " "Unsupported map type %s" % maptype
+                "Unable to write semantic label. " "Unsupported map type %s" % maptype
             )
             return -2
     except:
@@ -602,7 +602,7 @@ def _write_band_reference(lock, conn, data):
 ###############################################################################
 
 
-def _remove_band_reference(lock, conn, data):
+def _remove_semantic_label(lock, conn, data):
     """Remove the file based GRASS band identifier.
 
     The value to be send via pipe is the return value of G_remove_misc.
@@ -621,10 +621,10 @@ def _remove_band_reference(lock, conn, data):
         # layer = data[4]
 
         if maptype == RPCDefs.TYPE_RASTER:
-            check = libgis.G_remove_misc("cell_misc", "bandref", name)
+            check = libgis.G_remove_misc("cell_misc", "semantic_label", name)
         else:
             logging.error(
-                "Unable to remove band reference. " "Unsupported map type %s" % maptype
+                "Unable to remove semantic label. " "Unsupported map type %s" % maptype
             )
             return -2
     except:
@@ -1117,9 +1117,9 @@ def c_library_server(lock, conn):
     functions[RPCDefs.G_LOCATION] = _get_location
     functions[RPCDefs.G_GISDBASE] = _get_gisdbase
     functions[RPCDefs.READ_MAP_FULL_INFO] = _read_map_full_info
-    functions[RPCDefs.WRITE_BAND_REFERENCE] = _write_band_reference
-    functions[RPCDefs.READ_BAND_REFERENCE] = _read_band_reference
-    functions[RPCDefs.REMOVE_BAND_REFERENCE] = _remove_band_reference
+    functions[RPCDefs.WRITE_SEMANTIC_LABEL] = _write_semantic_label
+    functions[RPCDefs.READ_SEMANTIC_LABEL] = _read_semantic_label
+    functions[RPCDefs.REMOVE_SEMANTIC_LABEL] = _remove_semantic_label
     functions[RPCDefs.G_FATAL_ERROR] = _fatal_error
 
     libgis.G_gisinit("c_library_server")
@@ -1449,8 +1449,8 @@ class CLibrariesInterface(RPCServerBase):
         )
         return self.safe_receive("write_raster_timestamp")
 
-    def remove_raster_band_reference(self, name, mapset):
-        """Remove a file based raster band reference
+    def remove_raster_semantic_label(self, name, mapset):
+        """Remove a file based raster semantic label
 
         :param name: The name of the map
         :param mapset: The mapset of the map
@@ -1458,48 +1458,48 @@ class CLibrariesInterface(RPCServerBase):
         """
         self.check_server()
         self.client_conn.send(
-            [RPCDefs.REMOVE_BAND_REFERENCE, RPCDefs.TYPE_RASTER, name, mapset, None]
+            [RPCDefs.REMOVE_SEMANTIC_LABEL, RPCDefs.TYPE_RASTER, name, mapset, None]
         )
-        return self.safe_receive("remove_raster_timestamp")
+        return self.safe_receive("remove_raster_semantic_label")
 
-    def read_raster_band_reference(self, name, mapset):
-        """Read a file based raster band reference
+    def read_raster_semantic_label(self, name, mapset):
+        """Read a file based raster semantic label
 
-        Returns band reference or None
+        Returns semantic label or None
 
         :param name: The name of the map
         :param mapset: The mapset of the map
-        :returns: The return value of Rast_read_bandref
+        :returns: The return value of Rast_read_semantic_label
         """
         self.check_server()
         self.client_conn.send(
-            [RPCDefs.READ_BAND_REFERENCE, RPCDefs.TYPE_RASTER, name, mapset, None]
+            [RPCDefs.READ_SEMANTIC_LABEL, RPCDefs.TYPE_RASTER, name, mapset, None]
         )
-        return self.safe_receive("read_raster_band_reference")
+        return self.safe_receive("read_raster_semantic_label")
 
-    def write_raster_band_reference(self, name, mapset, band_reference):
-        """Write a file based raster band reference
+    def write_raster_semantic_label(self, name, mapset, semantic_label):
+        """Write a file based raster semantic label
 
         Note:
-            Only band references of maps from the current mapset can be written.
+            Only semantic labels of maps from the current mapset can be written.
 
         :param name: The name of the map
         :param mapset: The mapset of the map
-        :param band_reference: band reference identifier
+        :param semantic_label: semantic label
         :returns: always True
         """
         self.check_server()
         self.client_conn.send(
             [
-                RPCDefs.WRITE_BAND_REFERENCE,
+                RPCDefs.WRITE_SEMANTIC_LABEL,
                 RPCDefs.TYPE_RASTER,
                 name,
                 mapset,
                 None,
-                band_reference,
+                semantic_label,
             ]
         )
-        return self.safe_receive("write_raster_band_reference")
+        return self.safe_receive("write_raster_semantic_label")
 
     def raster3d_map_exists(self, name, mapset):
         """Check if a 3D raster map exists in the spatial database

+ 4 - 4
python/grass/temporal/extract.py

@@ -266,10 +266,10 @@ def extract_dataset(
                     new_map.set_temporal_extent(old_map.get_temporal_extent())
 
                     if type == "raster":
-                        # Set the band reference
-                        band_reference = old_map.metadata.get_band_reference()
-                        if band_reference is not None:
-                            new_map.set_band_reference(band_reference)
+                        # Set the semantic label
+                        semantic_label = old_map.metadata.get_semantic_label()
+                        if semantic_label is not None:
+                            new_map.set_semantic_label(semantic_label)
 
                     # Insert map in temporal database
                     new_map.insert(dbif)

+ 1 - 1
python/grass/temporal/mapcalc.py

@@ -107,7 +107,7 @@ def dataset_mapcalculator(
     input_name_list_uniq = []
     for input_name in input_name_list:
         ds = open_old_stds(input_name, type, dbif)
-        ds_name = ds.get_name(band_reference=False)
+        ds_name = ds.get_name(semantic_label=False)
         if ds_name not in input_name_list_uniq:
             input_name_list_uniq.append(ds_name)
     do_sampling = len(input_name_list_uniq) > 1

+ 17 - 17
python/grass/temporal/metadata.py

@@ -338,7 +338,7 @@ class RasterMetadata(RasterMetadataBase):
         ewres=None,
         min=None,
         max=None,
-        band_reference=None,
+        semantic_label=None,
     ):
 
         RasterMetadataBase.__init__(
@@ -355,21 +355,21 @@ class RasterMetadata(RasterMetadataBase):
             max,
         )
 
-        self.set_band_reference(band_reference)
+        self.set_semantic_label(semantic_label)
 
-    def set_band_reference(self, band_reference):
-        """Set the band reference identifier"""
-        self.D["band_reference"] = band_reference
+    def set_semantic_label(self, semantic_label):
+        """Set the semantic label identifier"""
+        self.D["semantic_label"] = semantic_label
 
-    def get_band_reference(self):
-        """Get the band reference identifier
+    def get_semantic_label(self):
+        """Get the semantic label identifier
         :return: None if not found"""
-        if "band_reference" in self.D:
-            return self.D["band_reference"]
+        if "semantic_label" in self.D:
+            return self.D["semantic_label"]
         else:
             return None
 
-    band_reference = property(fget=get_band_reference, fset=set_band_reference)
+    semantic_label = property(fget=get_semantic_label, fset=set_semantic_label)
 
     def _print_info_body(self, shell=False):
         """Print information about this class (body part).
@@ -377,11 +377,11 @@ class RasterMetadata(RasterMetadataBase):
         :param bool shell: True for human readable style otherwise shell style
         """
         super()._print_info_body(shell)
-        # band reference section (raster specific only)
+        # semantic label section (raster specific only)
         if shell:
-            print("band_reference=" + str(self.get_band_reference()))
+            print("semantic_label=" + str(self.get_semantic_label()))
         else:
-            print(" | Band reference:............. " + str(self.get_band_reference()))
+            print(" | Semantic label:............. " + str(self.get_semantic_label()))
 
 
 ###############################################################################
@@ -1404,7 +1404,7 @@ class STRDSMetadata(STDSRasterMetadataBase):
         :return: None if not found
         """
 
-        sql = "SELECT distinct band_reference FROM %s WHERE %s.id " % (
+        sql = "SELECT distinct semantic_label FROM %s WHERE %s.id " % (
             "raster_metadata",
             "raster_metadata",
         )
@@ -1421,11 +1421,11 @@ class STRDSMetadata(STDSRasterMetadataBase):
             string = ""
             count = 0
             for row in rows:
-                if row["band_reference"]:
+                if row["semantic_label"]:
                     if count == 0:
-                        string += row["band_reference"]
+                        string += row["semantic_label"]
                     else:
-                        string += ",%s" % row["band_reference"]
+                        string += ",%s" % row["semantic_label"]
                     count += 1
 
             if count > 0:

+ 6 - 6
python/grass/temporal/open_stds.py

@@ -44,23 +44,23 @@ def open_old_stds(name, type, dbif=None):
     """
     msgr = get_tgis_message_interface()
 
-    # Check if the dataset name contains the mapset and the band reference as well
+    # Check if the dataset name contains the mapset and the semantic label as well
     if name.find("@") < 0:
         mapset = get_current_mapset()
     else:
         name, mapset = name.split("@")
-    band_ref = None
+    semantic_label = None
     if name.find(".") > -1:
         try:
-            name, band_ref = name.split(".")
+            name, semantic_label = name.split(".")
         except ValueError:
             msgr.fatal("Invalid name of the space time dataset. Only one dot allowed.")
     id = name + "@" + mapset
 
     if type == "strds" or type == "rast" or type == "raster":
         sp = dataset_factory("strds", id)
-        if band_ref:
-            sp.set_band_reference(band_ref)
+        if semantic_label:
+            sp.set_semantic_label(semantic_label)
     elif (
         type == "str3ds"
         or type == "raster3d"
@@ -124,7 +124,7 @@ def check_new_stds(name, type, dbif=None, overwrite=False):
 
     if type == "strds" or type == "rast" or type == "raster":
         if name.find(".") > -1:
-            # a dot is used as a separator for band reference filtering
+            # a dot is used as a separator for semantic label filtering
             msgr.fatal(
                 _("Illegal dataset name <{}>. " "Character '.' not allowed.").format(
                     name

+ 20 - 20
python/grass/temporal/register.py

@@ -80,7 +80,7 @@ def register_maps_in_space_time_dataset(
     """
     start_time_in_file = False
     end_time_in_file = False
-    band_reference_in_file = False
+    semantic_label_in_file = False
 
     msgr = get_tgis_message_interface()
 
@@ -167,29 +167,29 @@ def register_maps_in_space_time_dataset(
 
             line_list = line.split(fs)
 
-            # Detect start and end time (and band reference)
+            # Detect start and end time (and semantic label)
             if len(line_list) == 2:
                 start_time_in_file = True
                 end_time_in_file = False
-                band_reference_in_file = False
+                semantic_label_in_file = False
             elif len(line_list) == 3:
                 start_time_in_file = True
-                # Check if last column is an end time or a band reference
+                # Check if last column is an end time or a semantic label
                 time_object = check_datetime_string(line_list[2])
                 if not sp.is_time_relative() and isinstance(time_object, datetime):
                     end_time_in_file = True
-                    band_reference_in_file = False
+                    semantic_label_in_file = False
                 else:
                     end_time_in_file = False
-                    band_reference_in_file = True
+                    semantic_label_in_file = True
             elif len(line_list) == 4:
                 start_time_in_file = True
                 end_time_in_file = True
-                band_reference_in_file = True
+                semantic_label_in_file = True
             else:
                 start_time_in_file = False
                 end_time_in_file = False
-                band_reference_in_file = False
+                semantic_label_in_file = False
 
             mapname = line_list[0].strip()
             row = {}
@@ -201,10 +201,10 @@ def register_maps_in_space_time_dataset(
             if start_time_in_file and not end_time_in_file:
                 row["start"] = line_list[1].strip()
 
-            if band_reference_in_file:
+            if semantic_label_in_file:
                 idx = 3 if end_time_in_file else 2
                 # case-sensitive, the user decides on the band name
-                row["band_reference"] = line_list[idx].strip()
+                row["semantic_label"] = line_list[idx].strip()
 
             row["id"] = AbstractMapDataset.build_id(mapname, mapset)
 
@@ -254,11 +254,11 @@ def register_maps_in_space_time_dataset(
         if "end" in maplist[count]:
             end = maplist[count]["end"]
 
-        # Use the band reference from file
-        if "band_reference" in maplist[count]:
-            band_reference = maplist[count]["band_reference"]
+        # Use the semantic label from file
+        if "semantic_label" in maplist[count]:
+            semantic_label = maplist[count]["semantic_label"]
         else:
-            band_reference = None
+            semantic_label = None
 
         is_in_db = False
 
@@ -402,15 +402,15 @@ def register_maps_in_space_time_dataset(
                 interval=interval,
             )
 
-        # Set the band reference (only raster type supported)
-        if band_reference:
-            # Band reference defined in input file
+        # Set the semantic label (only raster type supported)
+        if semantic_label:
+            # semantic label defined in input file
             # -> update raster metadata
             # -> write band identifier to GRASS data base
-            map.set_band_reference(band_reference)
+            map.set_semantic_label(semantic_label)
         else:
-            # Try to read band reference from GRASS data base if defined
-            map.read_band_reference_from_grass()
+            # Try to read semantic label from GRASS data base if defined
+            map.read_semantic_label_from_grass()
 
         if is_in_db:
             #  Gather the SQL update statement

+ 27 - 27
python/grass/temporal/space_time_datasets.py

@@ -346,42 +346,42 @@ class RasterDataset(AbstractMapDataset):
 
         return True
 
-    def read_band_reference_from_grass(self):
-        """Read the band identifier of this map from the map metadata
+    def read_semantic_label_from_grass(self):
+        """Read the semantic label of this map from the map metadata
         in the GRASS file system based spatial database and
-        set the internal band identifier that should be insert/updated
+        set the internal semantic label that should be insert/updated
         in the temporal database.
 
-        :return: True if success, False if band references could not be
+        :return: True if success, False if semantic labels could not be
                  read (due to an error or because not being present)
         """
 
-        band_ref = self.ciface.read_raster_band_reference(
+        semantic_label = self.ciface.read_raster_semantic_label(
             self.get_name(), self.get_mapset()
         )
 
-        if not band_ref:
+        if not semantic_label:
             return False
 
-        self.metadata.set_band_reference(band_ref)
+        self.metadata.set_semantic_label(semantic_label)
 
         return True
 
-    def write_band_reference_to_grass(self):
-        """Write the band identifier of this map into the map metadata in
+    def write_semantic_label_to_grass(self):
+        """Write the semantic label of this map into the map metadata in
         the GRASS file system based spatial database.
 
         Internally the libgis API functions are used for writing
 
         :return: True if success, False on error
         """
-        check = self.ciface.write_raster_band_reference(
-            self.get_name(), self.get_mapset(), self.metadata.get_band_reference()
+        check = self.ciface.write_raster_semantic_label(
+            self.get_name(), self.get_mapset(), self.metadata.get_semantic_label()
         )
         if check == -1:
             self.msgr.error(
                 _(
-                    "Unable to write band identifier for raster map <%s>"
+                    "Unable to write semantic label for raster map <%s>"
                     % (self.get_name())
                 )
             )
@@ -440,29 +440,29 @@ class RasterDataset(AbstractMapDataset):
             self.metadata.set_rows(rows)
             self.metadata.set_number_of_cells(ncells)
 
-            # Fill band reference if defined
-            band_ref = self.ciface.read_raster_band_reference(
+            # Fill semantic label if defined
+            semantic_label = self.ciface.read_raster_semantic_label(
                 self.get_name(), self.get_mapset()
             )
-            if band_ref:
-                self.metadata.set_band_reference(band_ref)
+            if semantic_label:
+                self.metadata.set_semantic_label(semantic_label)
 
             return True
 
         return False
 
-    def set_band_reference(self, band_reference):
-        """Set band reference identifier
+    def set_semantic_label(self, semantic_label):
+        """Set semantic label identifier
 
-        Metadata is updated in order to propagate band identifier into
+        Metadata is updated in order to propagate semantic label into
         temporal DB.
 
-        File-based band identifier stored in GRASS data base.
+        File-based semantic label stored in GRASS data base.
 
-        :param str band_reference: band reference identifier (eg. S2_1)
+        :param str semantic_label: semantic label (eg. S2_1)
         """
-        self.metadata.set_band_reference(band_reference)
-        self.write_band_reference_to_grass()
+        self.metadata.set_semantic_label(semantic_label)
+        self.write_semantic_label_to_grass()
 
 
 ###############################################################################
@@ -1196,12 +1196,12 @@ class SpaceTimeRasterDataset(AbstractSpaceTimeDataset):
     def __init__(self, ident):
         AbstractSpaceTimeDataset.__init__(self, ident)
 
-    def set_band_reference(self, band_reference):
-        """Set band reference identifier
+    def set_semantic_label(self, semantic_label):
+        """Set semantic label
 
-        :param str band_reference: band reference identifier (eg. S2_1)
+        :param str semantic_label: semantic label (eg. S2_1)
         """
-        self.band_reference = band_reference
+        self.semantic_label = semantic_label
 
     def is_stds(self):
         """Return True if this class is a space time dataset

+ 5 - 5
raster/r.info/main.c

@@ -45,7 +45,7 @@ int main(int argc, char **argv)
     const char *title;
     char tmp1[100], tmp2[100], tmp3[100];
     char timebuff[256];
-    char *units, *vdatum, *bandref;
+    char *units, *vdatum, *semantic_label;
     int i;
     CELL mincat = 0, maxcat = 0, cat;
     FILE *out;
@@ -120,7 +120,7 @@ int main(int argc, char **argv)
 
     vdatum = Rast_read_vdatum(name, "");
 
-    bandref = Rast_read_bandref(name, "");
+    semantic_label = Rast_read_semantic_label(name, "");
 
     /*Check the Timestamp */
     time_ok = G_read_raster_timestamp(name, "", &ts) > 0;
@@ -180,11 +180,11 @@ int main(int argc, char **argv)
 		     "  Type of Map:  %-20.20s Number of Categories: %-9s",
 		     hist_ok ? Rast_get_history(&hist, HIST_MAPTYPE) : "??", cats_ok ? tmp1 : "??");
 
-	compose_line(out, "  Data Type:    %-20.20s Band reference: %s ",
+	compose_line(out, "  Data Type:    %-20.20s Semantic label: %s ",
 		     (data_type == CELL_TYPE ? "CELL" :
 		      (data_type == DCELL_TYPE ? "DCELL" :
 		       (data_type == FCELL_TYPE ? "FCELL" : "??"))),
-             (bandref ? bandref : "(none)"));
+             (semantic_label ? semantic_label : "(none)"));
 
 	/* For now hide these unless they exist to keep the noise low. In
 	 *   future when the two are used more widely they can be printed
@@ -569,7 +569,7 @@ int main(int argc, char **argv)
 	    }
 	    fprintf(out, "units=%s\n", units ? units : "\"none\"");
 	    fprintf(out, "vdatum=%s\n", vdatum ? vdatum : "\"none\"");
-        fprintf(out, "bandref=%s\n", bandref ? bandref : "\"none\"");
+        fprintf(out, "semantic_label=%s\n", semantic_label ? semantic_label : "\"none\"");
 	    fprintf(out, "source1=\"%s\"\n", hist_ok ? Rast_get_history(&hist, HIST_DATSRC_1) : "\"none\"");
 	    fprintf(out, "source2=\"%s\"\n", hist_ok ? Rast_get_history(&hist, HIST_DATSRC_2) : "\"none\"");
 	    fprintf(out, "description=\"%s\"\n", hist_ok ? Rast_get_history(&hist, HIST_KEYWRD) : "\"none\"");

+ 1 - 1
raster/r.info/r.info.html

@@ -116,7 +116,7 @@ title="South-West Wake county: slope in degrees (slope_ned10m)"
 timestamp="none"
 units="none"
 vdatum="none"
-bandref="none"
+semantic_label="none"
 source1="raster elevation file elev_ned10m"
 source2=""
 description="generated by r.slope.aspect"

+ 24 - 24
raster/r.support/main.c

@@ -40,10 +40,10 @@ int main(int argc, char *argv[])
     struct GModule *module;
     struct Option *raster, *title_opt, *history_opt;
     struct Option *datasrc1_opt, *datasrc2_opt, *datadesc_opt;
-    struct Option *bandref_opt;
+    struct Option *semantic_label_opt;
     struct Option *map_opt, *units_opt, *vdatum_opt;
     struct Option *load_opt, *save_opt;
-    struct Flag *stats_flag, *null_flag, *del_flag, *bandref_rm_flag;
+    struct Flag *stats_flag, *null_flag, *del_flag, *semantic_label_rm_flag;
     int is_reclass;		/* Is raster reclass? */
     const char *infile;
     struct History hist;
@@ -135,19 +135,19 @@ int main(int argc, char *argv[])
     save_opt->guisection = _("Import / Export");
     save_opt->description = _("Text file in which to save history");
 
-    bandref_opt = G_define_option();
-    bandref_opt->key = "bandref";
-    bandref_opt->key_desc = "phrase";
-    bandref_opt->type = TYPE_STRING;
-    bandref_opt->required = NO;
-    bandref_opt->guisection = _("Band reference");
-    bandref_opt->description =
-	_("Band reference in form shortcut_name e.g. S2_8A");
+    semantic_label_opt = G_define_option();
+    semantic_label_opt->key = "semantic_label";
+    semantic_label_opt->key_desc = "phrase";
+    semantic_label_opt->type = TYPE_STRING;
+    semantic_label_opt->required = NO;
+    semantic_label_opt->guisection = _("Semantic label");
+    semantic_label_opt->description =
+	_("Semantic label e.g. S2_8A");
 
-    bandref_rm_flag = G_define_flag();
-    bandref_rm_flag->key = 'b';
-    bandref_rm_flag->guisection = _("Band reference");
-    bandref_rm_flag->description = _("Delete the band reference");
+    semantic_label_rm_flag = G_define_flag();
+    semantic_label_rm_flag->key = 'b';
+    semantic_label_rm_flag->guisection = _("Semantic label");
+    semantic_label_rm_flag->description = _("Delete the semantic label");
 
     stats_flag = G_define_flag();
     stats_flag->key = 's';
@@ -174,9 +174,9 @@ int main(int argc, char *argv[])
     if (!mapset || strcmp(mapset, G_mapset()) != 0)
 	G_fatal_error(_("Raster map <%s> not found in current mapset"), infile);
 
-    if (bandref_rm_flag->answer && bandref_opt->answer)
-        G_fatal_error(_("Band reference removal and setting band "
-                        "reference values simultaneously doesn't make sense"));
+    if (semantic_label_rm_flag->answer && semantic_label_opt->answer)
+        G_fatal_error(_("Semantic label removal and setting semantic "
+                        "label values simultaneously doesn't make sense"));
 
     Rast_get_cellhd(raster->answer, "", &cellhd);
     is_reclass = (Rast_is_reclass(raster->answer, "", rname, rmapset) > 0);
@@ -284,21 +284,21 @@ int main(int argc, char *argv[])
 	Rast_free_cats(&cats);
     }
 
-    if (bandref_opt->answer) {
-        if (Rast_legal_bandref(bandref_opt->answer) == false)
-            G_fatal_error(_("Provided band reference is not valid. "
+    if (semantic_label_opt->answer) {
+        if (Rast_legal_semantic_label(semantic_label_opt->answer) == false)
+            G_fatal_error(_("Provided semantic label is not valid. "
                             "See documentation for valid examples"));
 
-        Rast_write_bandref(infile, bandref_opt->answer);
+        Rast_write_semantic_label(infile, semantic_label_opt->answer);
     }
 
-    if (bandref_rm_flag->answer)
-        G_remove_misc("cell_misc", "bandref", infile);
+    if (semantic_label_rm_flag->answer)
+        G_remove_misc("cell_misc", "semantic_label", infile);
 
     if (title_opt->answer || history_opt->answer || units_opt->answer
 	|| vdatum_opt->answer || datasrc1_opt->answer || datasrc2_opt->answer
 	|| datadesc_opt->answer || map_opt->answer
-	|| bandref_opt->answer || bandref_rm_flag->answer)
+	|| semantic_label_opt->answer || semantic_label_rm_flag->answer)
 	exit(EXIT_SUCCESS);
 
 

+ 6 - 8
raster/r.support/r.support.html

@@ -2,17 +2,15 @@
 
 <b>r.support</b> allows the user to create and/or edit raster map support 
 information. Editing of raster map color tables, category labels, header, 
-history, band reference elements and title is supported.
+history, semantic label elements and title is supported.
 Category labels can also be copied from another raster map.
 
 <h3>Raster band management</h3>
-Raster band reference concept is similar to dimension name in other GIS and
+Raster semantic label concept is similar to dimension name in other GIS and
 remote sensing applications. Most common usage will be assigning a
 remote sensing platform sensor band ID to the raster, although any
-identifier is supported. Raster band reference is required to work with
+identifier is supported. Raster semantic label is suggested to work with
 imagery classification tools.<br>
-Band reference should be in form &lt;shortcut&gt;_&lt;bandname&gt; e.g.
-use <b>L5_1</b> if raster contains data from Landsat 5 visible blue (1) band.
 
 <h2>EXAMPLES</h2>
 These examples are based on the North Carolina dataset, more specfically the <em>landuse</em> raster map.
@@ -37,9 +35,9 @@ Copy the landuse map to the current mapset
 <div class="code"><pre>r.support map=my_landuse units=meter
 </pre></div>
 
-<h3>Set band reference</h3>
+<h3>Set semantic label</h3>
 Note: landuse map doesn't confirm to CORINE specification. This is an example only.
-<div class="code"><pre>r.support map=my_landuse bandref=CORINE_LULC
+<div class="code"><pre>r.support map=my_landuse semantic_label=CORINE_LULC
 </pre></div>
 
 <h2>NOTES</h2>
@@ -72,5 +70,5 @@ Micharl Shapiro, CERL: Original author<br>
 <a href="MAILTO:rez@touchofmadness.com">Brad Douglas</a>: GRASS 6 Port<br>
 M. Hamish Bowman: command line enhancements<br>
 Markus Neteler: category copy from other map<br>
-Maris Nartiss: band reference management
+Maris Nartiss: semantic label management
 

+ 17 - 15
raster/r.support/testsuite/test_r_support.py

@@ -19,15 +19,15 @@ from grass.pygrass.gis import Mapset
 from grass.pygrass import utils
 
 from grass.lib.gis import G_remove_misc
-from grass.lib.raster import Rast_read_bandref
+from grass.lib.raster import Rast_read_semantic_label
 
 
-class RSupportBandHandlingTestCase(TestCase):
+class RSupportSemanticLabelHandlingTestCase(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))
@@ -38,27 +38,29 @@ class RSupportBandHandlingTestCase(TestCase):
         cls.runModule("g.remove", flags="f", type="raster", name=cls.map)
 
     def test_exclusitivity(self):
-        self.assertModuleFail("r.support", map=self.map, bandref=self.bandref, b=True)
+        self.assertModuleFail(
+            "r.support", map=self.map, semantic_label=self.semantic_label, b=True
+        )
 
-    def test_bandref_invalid(self):
+    def test_semantic_label_invalid(self):
         self.assertModuleFail(
             "r.support",
             map=self.map,
-            bandref="".join(random.choices(string.ascii_letters, k=256)),
+            semantic_label="".join(random.choices(string.ascii_letters, k=256)),
         )
 
-    def test_set_bandref(self):
-        G_remove_misc("cell_misc", "bandref", self.map)
-        self.assertModule("r.support", map=self.map, bandref=self.bandref)
-        ret = utils.decode(Rast_read_bandref(self.map, self.mapset))
-        self.assertEqual(ret, self.bandref)
+    def test_set_semantic_label(self):
+        G_remove_misc("cell_misc", "semantic_label", self.map)
+        self.assertModule("r.support", map=self.map, semantic_label=self.semantic_label)
+        ret = utils.decode(Rast_read_semantic_label(self.map, self.mapset))
+        self.assertEqual(ret, self.semantic_label)
 
-    def test_remove_band_ref(self):
-        self.assertModule("r.support", map=self.map, bandref=self.bandref)
-        ret = Rast_read_bandref(self.map, self.mapset)
+    def test_remove_semantic_label(self):
+        self.assertModule("r.support", map=self.map, semantic_label=self.semantic_label)
+        ret = Rast_read_semantic_label(self.map, self.mapset)
         self.assertTrue(bool(ret))
         self.assertModule("r.support", map=self.map, b=True)
-        ret = Rast_read_bandref(self.map, self.mapset)
+        ret = Rast_read_semantic_label(self.map, self.mapset)
         self.assertFalse(bool(ret))
 
 

+ 8 - 13
scripts/g.bands/g.bands.py

@@ -5,7 +5,7 @@
 # MODULE:       g.bands
 # AUTHOR(S):    Martin Landa <landa.martin gmail com>
 #
-# PURPOSE:      Prints available band reference information used for multispectral data.
+# PURPOSE:      Prints available semantic label information used for multispectral data.
 #
 # COPYRIGHT:    (C) 2019 by mundialis GmbH & Co.KG, and the GRASS Development Team
 #
@@ -16,16 +16,16 @@
 #############################################################################
 
 # %module
-# % description: Prints available band reference information used for multispectral data.
+# % description: Prints available semantic label information used for multispectral data.
 # % keyword: general
 # % keyword: imagery
-# % keyword: band reference
+# % keyword: semantic label
 # % keyword: image collections
 # %end
 # %option
 # % key: pattern
 # % type: string
-# % description: Band reference search pattern (examples: L, S2, .*_2, S2_1)
+# % description: Semantic label search pattern (examples: L, S2, .*_2, S2_1)
 # % required: no
 # % multiple: no
 # %end
@@ -49,24 +49,19 @@ import grass.script as gs
 
 
 def main():
-    from grass.bandref import BandReferenceReader, BandReferenceReaderError
+    from grass.semantic_label import SemanticLabelReader, SemanticLabelReaderError
 
     kwargs = {}
     if "," in options["pattern"]:
         gs.fatal("Multiple values not supported")
-    if "_" in options["pattern"]:
-        # full band identifier specified
-        kwargs["shortcut"], kwargs["band"] = options["pattern"].split("_")
-    else:
-        # pattern
-        kwargs["shortcut"] = options["pattern"]
+    kwargs["semantic_label"] = options["pattern"]
     kwargs["extended"] = flags["e"]
 
     if options["operation"] == "print":
         try:
-            reader = BandReferenceReader()
+            reader = SemanticLabelReader()
             reader.print_info(**kwargs)
-        except BandReferenceReaderError as e:
+        except SemanticLabelReaderError as e:
             gs.fatal(e)
 
     return 0

+ 2 - 2
scripts/g.bands/testsuite/test_g_bands.py

@@ -17,9 +17,9 @@ class TestBandsSystemDefined(TestCase):
         nbands = self._number_of_bands()
 
         # get number of valid band identifiers by Bands lib
-        from grass.bandref import BandReferenceReader
+        from grass.semantic_label import SemanticLabelReader
 
-        nbands_ref = len(BandReferenceReader().get_bands())
+        nbands_ref = len(SemanticLabelReader().get_bands())
         self.assertEqual(nbands, nbands_ref)
 
     def test_number_s2(self):

+ 18 - 18
scripts/i.band/i.band.html

@@ -1,11 +1,11 @@
 <h2>DESCRIPTION</h2>
 
-<em>i.band</em> allows assigning a band reference information to a
-single raster map or to a list of specified raster maps. Band
-reference can be defined by <b>band</b> option. Already assigned band
-reference can be removed from a specified raster map
+<em>i.band</em> allows assigning a semantic label information to a
+single raster map or to a list of specified raster maps. Semantic
+label can be defined by <b>semantic_label</b> option. Already assigned semantic
+label can be removed from a specified raster map
 by <b>operation=remove</b>. The module also allows printing detailed
-band reference information already assigned to a raster map
+semantic label information already assigned to a raster map
 by <b>operation=print</b>.
 
 <p>
@@ -17,14 +17,14 @@ by <b>map</b> option.
 Note that <i>only raster maps from the current mapsets</i> can be modified.
 
 <p>
-For more information about band reference concept and supported sensors
+For more information about semantic label concept and supported sensors
 (generic multispectral system, Landsat-5, Landsat-7, Landsat-8, Sentinel-2)
 see the <em><a href="g.bands.html">g.bands</a></em> module.
 
 <p>
-Band references are supported by temporal GRASS modules. Name of
+Semantic labels are supported by temporal GRASS modules. Name of
 STRDS can be extended by band identifier in order to filter the result
-by a band reference. See
+by a semantic label. See
 <em><a href="t.register.html#support-for-band-references">t.register</a></em>,
 <em><a href="t.rast.list.html#filtering-the-result-by-band-references">t.rast.list</a></em>,
 <em><a href="t.info.html#space-time-dataset-with-band-references-assigned">t.info</a></em>
@@ -33,37 +33,37 @@ modules for examples.
 
 <h2>EXAMPLES</h2>
 
-<h3>Assign band reference to a single raster map</h3>
+<h3>Assign semantic label to a single raster map</h3>
 
 <div class="code"><pre>
-i.band map=T33UVR_20180506T100031_B01 band=S2_1
+i.band map=T33UVR_20180506T100031_B01 semantic_label=S2_1
 </pre></div>
 
-<h3>Assign band reference to a list of raster maps</h3>
+<h3>Assign semantic label to a list of raster maps</h3>
 
 <div class="code"><pre>
-i.band map=T33UVR_20180506T100031_B01,T33UVR_20180521T100029_B01 band=S2_1,S2_1
+i.band map=T33UVR_20180506T100031_B01,T33UVR_20180521T100029_B01 semantic_label=S2_1,S2_1
 </pre></div>
 
-<h3>Assign different band references to a list of raster maps</h3>
+<h3>Assign different semantic labels to a list of raster maps</h3>
 
 <div class="code"><pre>
-i.band map=T33UVR_20180506T100031_B01,T33UVR_20180506T100031_B02 band=S2_1,S2_2
+i.band map=T33UVR_20180506T100031_B01,T33UVR_20180506T100031_B02 semantic_label=S2_1,S2_2
 </pre></div>
 
-<h3>Remove band reference from a list of raster maps</h3>
+<h3>Remove semantic label from a list of raster maps</h3>
 
 <div class="code"><pre>
 i.band map=T33UVR_20180506T100031_B01,T33UVR_20180506T100031_B02 operation=remove
 </pre></div>
 
-<h3>Print band reference information about single raster map</h3>
+<h3>Print semantic label information about single raster map</h3>
 
 <div class="code"><pre>
 i.band map=T33UVR_20180506T100031_B01 operation=print
 </pre></div>
 
-<h3>Print extended band reference information for a list of raster map</h3>
+<h3>Print extended semantic label information for a list of raster map</h3>
 
 <div class="code"><pre>
 i.band map=T33UVR_20180506T100031_B01,T33UVR_20180506T100031_B02 operation=print
@@ -71,7 +71,7 @@ i.band map=T33UVR_20180506T100031_B01,T33UVR_20180506T100031_B02 operation=print
 
 <h2>KNOWN ISSUES</h2>
 
-<em>i.band</em> allows managing band references only related to 2D
+<em>i.band</em> allows managing semantic labels only related to 2D
 raster maps.
 
 <h2>SEE ALSO</h2>

+ 33 - 34
scripts/i.band/i.band.py

@@ -5,7 +5,7 @@
 # MODULE:       i.band
 # AUTHOR(S):    Martin Landa <landa.martin gmail com>
 #
-# PURPOSE:      Manages band reference information assigned to a single
+# PURPOSE:      Manages semantic label information assigned to a single
 #               raster map or to a list of raster maps.
 #
 # COPYRIGHT:    (C) 2019 by mundialis GmbH & Co.KG, and the GRASS Development Team
@@ -17,19 +17,19 @@
 #############################################################################
 
 # %module
-# % description: Manages band reference information assigned to a single raster map or to a list of raster maps.
+# % description: Manages semantic label information assigned to a single raster map or to a list of raster maps.
 # % keyword: general
 # % keyword: imagery
-# % keyword: band reference
+# % keyword: semantic label
 # % keyword: image collections
 # %end
 # %option G_OPT_R_MAPS
 # %end
 # %option
-# % key: band
+# % key: semantic_label
 # % type: string
 # % key_desc: name
-# % description: Name of band reference identifier (example: S2_1)
+# % description: Name of semantic label identifier (example: S2_1)
 # % required: no
 # % multiple: yes
 # %end
@@ -48,8 +48,8 @@ import grass.script as gs
 from grass.exceptions import GrassError, OpenError
 
 
-def print_map_band_reference(name, band_reader):
-    """Print band reference information assigned to a single raster map
+def print_map_semantic_label(name, label_reader):
+    """Print semantic label information assigned to a single raster map
 
     :param str name: raster map name
     """
@@ -57,21 +57,20 @@ def print_map_band_reference(name, band_reader):
 
     try:
         with RasterRow(name) as rast:
-            band_ref = rast.info.bandref
-            if band_ref:
-                shortcut, band = band_ref.split("_")
-                band_reader.print_info(shortcut, band)
+            semantic_label = rast.info.semantic_label
+            if semantic_label:
+                label_reader.print_info(semantic_label)
             else:
-                gs.info(_("No band reference assigned to <{}>").format(name))
+                gs.info(_("No semantic label assigned to <{}>").format(name))
     except OpenError as e:
         gs.error(_("Map <{}> not found").format(name))
 
 
-def manage_map_band_reference(name, band_ref):
-    """Manage band reference assigned to a single raster map
+def manage_map_semantic_label(name, semantic_label):
+    """Manage semantic label assigned to a single raster map
 
     :param str name: raster map name
-    :param str band_ref: band reference (None for dissociating band reference)
+    :param str semantic_label: semantic label (None for dissociating semantic label)
 
     :return int: return code
     """
@@ -79,21 +78,21 @@ def manage_map_band_reference(name, band_ref):
 
     try:
         with RasterRow(name) as rast:
-            if band_ref:
+            if semantic_label:
                 gs.debug(
-                    _("Band reference <{}> assigned to raster map <{}>").format(
-                        band_ref, name
+                    _("Semantic label <{}> assigned to raster map <{}>").format(
+                        semantic_label, name
                     ),
                     1,
                 )
             else:
                 gs.debug(
-                    _("Band reference dissociated from raster map <{}>").format(name), 1
+                    _("Semantic label dissociated from raster map <{}>").format(name), 1
                 )
             try:
-                rast.info.bandref = band_ref
+                rast.info.semantic_label = semantic_label
             except GrassError as e:
-                gs.error(_("Unable to assign/dissociate band reference. {}").format(e))
+                gs.error(_("Unable to assign/dissociate semantic label. {}").format(e))
                 return 1
     except OpenError as e:
         gs.error(_("Map <{}> not found in current mapset").format(name))
@@ -105,32 +104,32 @@ def manage_map_band_reference(name, band_ref):
 def main():
     maps = options["map"].split(",")
     if options["operation"] == "add":
-        if not options["band"]:
+        if not options["semantic_label"]:
             gs.fatal(
                 _("Operation {}: required parameter <{}> not set").format(
-                    options["operation"], "band"
+                    options["operation"], "semantic_label"
                 )
             )
-        bands = options["band"].split(",")
-        if len(bands) > 1 and len(bands) != len(maps):
-            gs.fatal(_("Number of maps differs from number of bands"))
+        semantic_labels = options["semantic_label"].split(",")
+        if len(semantic_labels) > 1 and len(semantic_labels) != len(maps):
+            gs.fatal(_("Number of maps differs from number of semantic labels"))
     else:
-        bands = [None]
+        semantic_labels = [None]
 
     if options["operation"] == "print":
-        from grass.bandref import BandReferenceReader
+        from grass.semantic_label import SemanticLabelReader
 
-        band_reader = BandReferenceReader()
+        label_reader = SemanticLabelReader()
     else:
-        band_reader = None
-    multi_bands = len(bands) > 1
+        label_reader = None
+    multi_labels = len(semantic_labels) > 1
     ret = 0
     for i in range(len(maps)):
-        band_ref = bands[i] if multi_bands else bands[0]
+        semantic_label = semantic_labels[i] if multi_labels else semantic_labels[0]
         if options["operation"] == "print":
-            print_map_band_reference(maps[i], band_reader)
+            print_map_semantic_label(maps[i], label_reader)
         else:
-            if manage_map_band_reference(maps[i], band_ref) != 0:
+            if manage_map_semantic_label(maps[i], semantic_label) != 0:
                 ret = 1
 
     return ret

+ 16 - 12
scripts/i.band/testsuite/test_i_band.py

@@ -7,11 +7,11 @@ from grass.pygrass.gis import Mapset
 from grass.pygrass.raster import RasterRow
 
 
-class TestBandsSystemDefined(TestCase):
+class TestSemanticLabelsSystemDefined(TestCase):
     @classmethod
     def setUpClass(cls):
         cls.map = tempname(10)
-        cls.bandref = "The_Doors"
+        cls.semantic_label = "The_Doors"
         cls.mapset = Mapset()
         cls.use_temp_region()
         cls.runModule("g.region", n=1, s=0, e=1, w=0, res=1)
@@ -22,32 +22,36 @@ class TestBandsSystemDefined(TestCase):
         cls.del_temp_region()
         cls.runModule("g.remove", flags="f", type="raster", name=cls.map)
 
-    def read_band_ref(self):
+    def read_semantic_label(self):
         with RasterRow(self.map) as rast:
-            band_ref = rast.info.bandref
+            semantic_label = rast.info.semantic_label
 
-        return band_ref
+        return semantic_label
 
-    def test_band_ref_assign_not_current_mapset(self):
+    def test_semantic_label_assign_not_current_mapset(self):
         if not self.mapset == "PERMANENT":
             self.mapset.name = "PERMANENT"
             a_map = self.mapset.glist(type="raster")[0]
-            module = SimpleModule("i.band", map=a_map, band=self.bandref)
+            module = SimpleModule(
+                "i.band", map=a_map, semantic_label=self.semantic_label
+            )
             self.assertModuleFail(module)
 
-    def test_band_ref_assign(self):
-        module = SimpleModule("i.band", map=self.map, band=self.bandref)
+    def test_semantic_label_assign(self):
+        module = SimpleModule(
+            "i.band", map=self.map, semantic_label=self.semantic_label
+        )
         self.assertModule(module)
 
         # check also using pygrass
-        self.assertEqual(self.read_band_ref(), self.bandref)
+        self.assertEqual(self.read_semantic_label(), self.semantic_label)
 
-    def test_band_ref_dissociate(self):
+    def test_semantic_label_dissociate(self):
         module = SimpleModule("i.band", operation="remove", map=self.map)
         self.assertModule(module)
 
         # check also using pygrass
-        self.assertEqual(self.read_band_ref(), None)
+        self.assertEqual(self.read_semantic_label(), None)
 
 
 if __name__ == "__main__":

+ 4 - 4
temporal/t.info/t.info.html

@@ -137,11 +137,11 @@ t.info input=2009_01_tempmean type=raster
  +----------------------------------------------------------------------------+
 </pre></div>
 
-<h3>Space time dataset with band references assigned</h3>
+<h3>Space time dataset with semantic labels assigned</h3>
 
-This information is printed only when band references have been assigned
+This information is printed only when semantic labels have been assigned
 to registered raster maps by <em><a href="i.band.html">i.band</a></em>
-or <em><a href="t.register.html#support-for-band-references">t.register</a></em> module.
+or <em><a href="t.register.html#support-for-semantic-labels">t.register</a></em> module.
 
 <div class="code"><pre>
 t.info input=test
@@ -158,7 +158,7 @@ Similarly for temporal maps information:
 t.info input=T33UYP_20190331T094039_B01 type=raster
 ...
  +-------------------- Metadata information ----------------------------------+
- | Band reference:............. S2_1
+ | Semantic label:............. S2_1
 ...
 </pre></div>
 

+ 2 - 2
temporal/t.list/t.list.py

@@ -52,7 +52,7 @@
 # % guisection: Formatting
 # % required: no
 # % multiple: yes
-# % options: id,name,band_reference,creator,mapset,number_of_maps,creation_time,start_time,end_time,interval,north,south,west,east,granularity
+# % options: id,name,semantic_label,creator,mapset,number_of_maps,creation_time,start_time,end_time,interval,north,south,west,east,granularity
 # % answer: id
 # %end
 
@@ -64,7 +64,7 @@
 # % guisection: Selection
 # % required: no
 # % multiple: yes
-# % options: id,name,band_reference,creator,mapset,number_of_maps,creation_time,start_time,end_time,north,south,west,east,granularity,all
+# % options: id,name,semantic_label,creator,mapset,number_of_maps,creation_time,start_time,end_time,north,south,west,east,granularity,all
 # % answer: id
 # %end
 

+ 8 - 8
temporal/t.rast.list/t.rast.list.html

@@ -184,16 +184,16 @@ id|name|mapset|start_time|end_time|interval_length|distance_from_begin
 For the <em>deltagaps</em> value you can see the example for space time
 vector dataset <a href="t.vect.list.html#using-method-option">t.vect.list</a>
 
-<h3>Filtering the result by band references</h3>
+<h3>Filtering the result by semantic label</h3>
 
-Band reference can be assigned to raster maps
+Semantic label can be assigned to raster maps
 by <em><a href="i.band.html">i.band</a></em> module or even when
 registrating raster maps into STRDS
-by <em><a href="t.register.html#support-for-band-references">t.register</a></em>.
+by <em><a href="t.register.html#support-for-semantic-labels">t.register</a></em>.
 
 <p>
-Name of STRDS can be extended by band reference identifier used for
-filtering. Name of STRDS and band reference is split by a <i>single
+Name of STRDS can be extended by semantic label used for
+filtering. Name of STRDS and semantic label is split by a <i>single
 dot</i>.
 
 <div class="code"><pre>
@@ -201,12 +201,12 @@ t.rast.list input=test.S2_1
 </pre></div>
 
 
-Note that band reference filtering is <i>supported by all temporal
+Note that semantic label filtering is <i>supported by all temporal
 modules</i>.
 
 <p>
-Also note that only STRDS can be filtered by band reference
-identifier, see <em><a href="i.band.html#known-issues">i.band</a></em> for
+Also note that only STRDS can be filtered by semantic label,
+see <em><a href="i.band.html#known-issues">i.band</a></em> for
 current limitations.
 
 

+ 2 - 2
temporal/t.rast.list/t.rast.list.py

@@ -39,7 +39,7 @@
 # % guisection: Formatting
 # % required: no
 # % multiple: yes
-# % options: id,name,band_reference,creator,mapset,temporal_type,creation_time,start_time,end_time,north,south,west,east,nsres,ewres,cols,rows,number_of_cells,min,max
+# % options: id,name,semantic_label,creator,mapset,temporal_type,creation_time,start_time,end_time,north,south,west,east,nsres,ewres,cols,rows,number_of_cells,min,max
 # % answer: start_time
 # %end
 
@@ -50,7 +50,7 @@
 # % guisection: Selection
 # % required: no
 # % multiple: yes
-# % options: id,name,band_reference,creator,mapset,temporal_type,creation_time,start_time,end_time,north,south,west,east,nsres,ewres,cols,rows,number_of_cells,min,max
+# % options: id,name,semantic_label,creator,mapset,temporal_type,creation_time,start_time,end_time,north,south,west,east,nsres,ewres,cols,rows,number_of_cells,min,max
 # % answer: name,mapset,start_time,end_time
 # %end
 

+ 4 - 4
temporal/t.rast.mapcalc/t.rast.mapcalc.html

@@ -153,10 +153,10 @@ t.rast.list tempmean_monthly columns=name,start_time,min,max | grep 01-01
 2012_01_tempmean|2012-01-01 00:00:00|-0.534994|9.69511
 </pre></div>
 
-<h3>Band reference filtering</h3>
+<h3>Semantic label filtering</h3>
 
-<em>t.rast.mapcalc</em> supports band reference filtering similarly
-to <em><a href="t.rast.list.html#filtering-the-result-by-band-references">t.rast.list</a></em>. In
+<em>t.rast.mapcalc</em> supports semantic label filtering similarly
+to <em><a href="t.rast.list.html#filtering-the-result-by-semantic-label">t.rast.list</a></em>. In
 example below a new STRDS will be created and filled by NDVI products.
 
 <div class="code"><pre>
@@ -164,7 +164,7 @@ t.rast.mapcalc inputs=test.S2_8,test.S2_4 output=ndvi basename=ndvi \
      expression="float(test.S2_8 - test.S2_4) / (test.S2_8 + test.S2_4)"
 </pre></div>
 
-For more information about band reference concept
+For more information about semantic label concept
 see <em><a href="g.bands.html">g.bands</a></em> module.
 
 <h2>SEE ALSO</h2>

+ 8 - 8
temporal/t.register/t.register.html

@@ -113,14 +113,14 @@ prec_5|2002-01-01|2002-04-01
 prec_6|2002-04-01|2002-07-01
 </pre></div>
 
-<h3>Support for band references</h3>
+<h3>Support for semantic labels</h3>
 
-For more information about band references and image collections
+For more information about semantic labels and image collections
 see <em><a href="g.bands.html">g.bands</a></em> module.
 
 <p>
 Specification of map names and absolute start time (datetime) of the time
-instances. The last column indicates related band references.
+instances. The last column indicates related semantic label.
 
 <div class="code"><pre>
 T33UYP_20190331T094039_B01|2019-03-31 09:40:39|S2_1
@@ -137,16 +137,16 @@ T33UYP_20190331T094039_B03|2019-03-31 09:40:39|S2_3
 T33UYP_20190331T094039_B09|2019-03-31 09:40:39|S2_9
 </pre></div>
 
-In this case <em>t.register</em> assignes to given raster maps band
-references similarly as
+In this case <em>t.register</em> assigns to given raster maps
+a semantic label similarly as
 <em><a href="i.band.html">i.band</a></em> does.
 
 Such registered raster maps is possible
-to <a href="t.rast.list.html#filtering-the-result-by-band-references">filter
-by a band references</a>.
+to <a href="t.rast.list.html#filtering-the-result-by-semantic-label">filter
+by a semantic label</a>.
 
 <p>
-Please note that raster maps with band references assigned can be
+Please note that raster maps with semantic labels assigned can be
 registered only in STRDS created in TGIS DB version 3 or
 higher. <i>Older versions of TGIS DB are not supported.</i> TGIS DB
 version can be checked <em><a href="t.connect.html">t.connect</a></em>

+ 1 - 1
temporal/t.upgrade/t.upgrade.html

@@ -2,7 +2,7 @@
 
 This module upgrades the temporal database in the current mapset
 from version 2 (default in GRASS 7) to 3 (default in GRASS 8).
-The version 3 introduces a band reference support, see
+The version 3 introduces a semantic label support, see
 <em><a href="g.bands.html">g.bands</a></em> for details.
 
 <h2>EXAMPLE</h2>