sig.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <grass/imagery.h>
  4. #include <grass/glocale.h>
  5. /*!
  6. * \brief Initialize struct Signature before use
  7. *
  8. * No need to call before calling I_read_signatures.
  9. *
  10. * \param *Signature to initialize
  11. * \param nbands band (imagery group member) count
  12. */
  13. int I_init_signatures(struct Signature *S, int nbands)
  14. {
  15. S->nbands = nbands;
  16. S->semantic_labels = (char **)G_malloc(nbands * sizeof(char **));
  17. for (int i = 0; i < nbands; i++)
  18. S->semantic_labels[i] = NULL;
  19. S->nsigs = 0;
  20. S->sig = NULL;
  21. S->title[0] = 0;
  22. return 0;
  23. }
  24. #define SIG struct One_Sig
  25. int I_new_signature(struct Signature *S)
  26. {
  27. int n;
  28. int i;
  29. i = S->nsigs++;
  30. S->sig = (SIG *) G_realloc(S->sig, S->nsigs * sizeof(SIG));
  31. S->sig[i].mean = (double *)G_calloc(S->nbands, sizeof(double));
  32. S->sig[i].var = (double **)G_calloc(S->nbands, sizeof(double *));
  33. for (n = 0; n < S->nbands; n++)
  34. S->sig[i].var[n] = (double *)G_calloc(S->nbands, sizeof(double));
  35. S->sig[i].status = 0;
  36. S->sig[i].have_color = 0;
  37. sprintf(S->sig[i].desc, "Class %d", i + 1);
  38. return S->nsigs;
  39. }
  40. /*!
  41. * \brief Free memory allocated for struct Signature
  42. *
  43. * One must call I_init_signatures() to re-use struct after it has been
  44. * passed to this function.
  45. *
  46. * \param *Signature to free
  47. *
  48. * \return always 0
  49. */
  50. int I_free_signatures(struct Signature *S)
  51. {
  52. int n;
  53. int i;
  54. for (i = 0; i < S->nsigs; i++) {
  55. for (n = 0; n < S->nbands; n++)
  56. free(S->sig[i].var[n]);
  57. free(S->sig[i].var);
  58. free(S->sig[i].mean);
  59. }
  60. free(S->sig);
  61. for (n = 0; n < S->nbands; n++)
  62. free(S->semantic_labels[n]);
  63. free(S->semantic_labels);
  64. S->sig = NULL;
  65. S->semantic_labels = NULL;
  66. S->nbands = 0;
  67. S->nsigs = 0;
  68. S->title[0] = '\0';
  69. return 0;
  70. }
  71. int I_read_one_signature(FILE * fd, struct Signature *S)
  72. {
  73. int n;
  74. int i;
  75. struct One_Sig *s;
  76. while ((i = fgetc(fd)) != EOF)
  77. if (i == '#')
  78. break;
  79. if (i != '#')
  80. return 0;
  81. i = I_new_signature(S);
  82. s = &S->sig[i - 1];
  83. I_get_to_eol(s->desc, sizeof(s->desc), fd);
  84. G_strip(s->desc);
  85. if (fscanf(fd, "%d", &s->npoints) != 1)
  86. return -1;
  87. for (i = 0; i < S->nbands; i++) {
  88. if (fscanf(fd, "%lf", &s->mean[i]) != 1)
  89. return -1;
  90. }
  91. for (i = 0; i < S->nbands; i++) {
  92. for (n = 0; n <= i; n++) {
  93. if (fscanf(fd, "%lf", &s->var[i][n]) != 1)
  94. return -1;
  95. s->var[n][i] = s->var[i][n]; /* added 28 aug 91 */
  96. }
  97. }
  98. if (fscanf(fd, "%f%f%f", &s->r, &s->g, &s->b) == 3 &&
  99. s->r >= 0.0 && s->r <= 1.0 &&
  100. s->g >= 0.0 && s->g <= 1.0 && s->b >= 0.0 && s->b <= 1.0)
  101. s->have_color = 1;
  102. s->status = 1;
  103. return 1;
  104. }
  105. /*!
  106. * \brief Read signatures from file
  107. *
  108. * File stream should be opened in advance by call to
  109. * I_fopen_signature_file_old()
  110. * It is up to caller to fclose the file stream afterwards.
  111. *
  112. * There is no need to initialize struct Signature in advance, as this
  113. * function internally calls I_init_signatures.
  114. *
  115. * \param pointer to FILE*
  116. * \param pointer to struct Signature *S
  117. *
  118. * \return 1 on success, -1 on failure
  119. */
  120. int I_read_signatures(FILE * fd, struct Signature *S)
  121. {
  122. int ver, n, pos;
  123. char c, prev;
  124. char semantic_label[GNAME_MAX];
  125. I_init_signatures(S, 0);
  126. S->title[0] = 0;
  127. /* File of signatures must start with its version number */
  128. if (fscanf(fd, "%d", &ver) != 1) {
  129. G_warning(_("Invalid signature file"));
  130. return -1;
  131. }
  132. /* Current version number is 1 */
  133. if (ver != 1) {
  134. G_warning(_("Invalid signature file version"));
  135. return -1;
  136. }
  137. /* Goto title line and strip initial # */
  138. while ((c = (char)fgetc(fd)) != EOF)
  139. if (c == '#')
  140. break;
  141. I_get_to_eol(S->title, sizeof(S->title), fd);
  142. G_strip(S->title);
  143. /* Read semantic labels and count them to set nbands */
  144. n = 0;
  145. pos = 0;
  146. S->semantic_labels = (char **)G_realloc(S->semantic_labels, (n + 1) * sizeof(char **));
  147. while ((c = (char)fgetc(fd)) != EOF) {
  148. if (c == '\n') {
  149. if (prev != ' ') {
  150. semantic_label[pos] = '\0';
  151. S->semantic_labels[n] = G_store(semantic_label);
  152. n++;
  153. }
  154. S->nbands = n;
  155. break;
  156. }
  157. if (c == ' ') {
  158. semantic_label[pos] = '\0';
  159. S->semantic_labels[n] = G_store(semantic_label);
  160. n++;
  161. /* [n] is 0 based thus: (n + 1) */
  162. S->semantic_labels = (char **)G_realloc(S->semantic_labels, (n + 1) * sizeof(char **));
  163. pos = 0;
  164. prev = c;
  165. continue;
  166. }
  167. /* Semantic labels are limited to GNAME_MAX - 1 + \0 in length;
  168. * n is 0-based */
  169. if (pos == (GNAME_MAX - 2)) {
  170. G_warning(_("Invalid signature file: semantic label length limit exceeded"));
  171. return -1;
  172. }
  173. semantic_label[pos] = c;
  174. pos++;
  175. prev = c;
  176. }
  177. if (!(S->nbands > 0)) {
  178. G_warning(_("Signature file does not contain bands"));
  179. return -1;
  180. }
  181. while ((n = I_read_one_signature(fd, S)) == 1) ;
  182. if (n < 0)
  183. return -1;
  184. if (S->nsigs == 0)
  185. return -1;
  186. return 1;
  187. }
  188. /*!
  189. * \brief Write signatures to file
  190. *
  191. * File stream should be opened in advance by call to
  192. * I_fopen_signature_file_new()
  193. * It is up to caller to fclose the file stream afterwards.
  194. *
  195. * \param pointer to FILE*
  196. * \param pointer to struct Signature *S
  197. *
  198. * \return always 1
  199. */
  200. int I_write_signatures(FILE * fd, struct Signature *S)
  201. {
  202. int k;
  203. int n;
  204. int i;
  205. struct One_Sig *s;
  206. /* Version of signatures file structure.
  207. * Increment if file structure changes.
  208. */
  209. fprintf(fd, "1\n");
  210. /* Title of signatures */
  211. fprintf(fd, "#%s\n", S->title);
  212. /* A list of space separated semantic labels for each
  213. * raster map used to generate sigs. */
  214. for (k = 0; k < S->nbands; k++) {
  215. fprintf(fd, "%s ", S->semantic_labels[k]);
  216. }
  217. fprintf(fd, "\n");
  218. /* A signature for each target class */
  219. for (k = 0; k < S->nsigs; k++) {
  220. s = &S->sig[k];
  221. if (s->status != 1)
  222. continue;
  223. /* Label for each class represented by this signature */
  224. fprintf(fd, "#%s\n", s->desc);
  225. /* Point count used to generate signature */
  226. fprintf(fd, "%d\n", s->npoints);
  227. /* Values are in the same order as semantic labels */
  228. for (i = 0; i < S->nbands; i++)
  229. fprintf(fd, "%g ", s->mean[i]);
  230. fprintf(fd, "\n");
  231. for (i = 0; i < S->nbands; i++) {
  232. for (n = 0; n <= i; n++)
  233. fprintf(fd, "%g ", s->var[i][n]);
  234. fprintf(fd, "\n");
  235. }
  236. if (s->have_color)
  237. fprintf(fd, "%g %g %g\n", s->r, s->g, s->b);
  238. }
  239. return 1;
  240. }
  241. /*!
  242. * \brief Reorder struct Signature to match imagery group member order
  243. *
  244. * The function will check for semantic label match between signature struct
  245. * and imagery group.
  246. *
  247. * In the case of a complete semantic label match, values of passed in
  248. * struct Signature are reordered to match the order of imagery group items.
  249. *
  250. * If all semantic labels are not identical (in
  251. * arbitrary order), function will return two dimensional array with
  252. * comma separated list of:
  253. * - [0] semantic labels present in the signature struct but
  254. * absent in the imagery group
  255. * - [1] semantic labels present in the imagery group but
  256. * absent in the signature struct
  257. *
  258. * If no mismatch of simantic labels for signatures or imagery group are
  259. * detected (== all are present in the other list), a NULL value will be
  260. * returned in the particular list of mismatches (not an empty string).
  261. * For example:
  262. * \code if (ret && ret[1]) printf("List of imagery group bands without signatures: %s\n, ret[1]); \endcode
  263. *
  264. * \param *Signature existing signatures to check & sort
  265. * \param *Ref group reference
  266. *
  267. * \return NULL successfully sorted
  268. * \return err_array two comma separated lists of mismatches
  269. */
  270. char **I_sort_signatures_by_semantic_label(struct Signature *S, const struct Ref *R) {
  271. unsigned int total, complete;
  272. unsigned int *match1, *match2, mc1, mc2, *new_order;
  273. double **new_means, ***new_vars;
  274. char **group_semantic_labels, **mismatches, **new_semantic_labels;
  275. /* Safety measure. Untranslated as this should not happen in production! */
  276. if (S->nbands < 1 || R->nfiles < 1)
  277. G_fatal_error("Programming error. Invalid length structs passed to "
  278. "I_sort_signatures_by_semantic_label(%d, %d);", S->nbands, R->nfiles);
  279. /* Obtain group semantic labels */
  280. group_semantic_labels = (char **)G_malloc(R->nfiles * sizeof(char *));
  281. for (unsigned int j = R->nfiles; j--;) {
  282. group_semantic_labels[j] = Rast_get_semantic_label_or_name(R->file[j].name, R->file[j].mapset);
  283. }
  284. /* If lengths are not equal, there will be a mismatch */
  285. complete = S->nbands == R->nfiles;
  286. /* Initialize match tracker */
  287. new_order = (unsigned int *)G_malloc(S->nbands * sizeof(unsigned int));
  288. match1 = (unsigned int *)G_calloc(S->nbands, sizeof(unsigned int));
  289. match2 = (unsigned int *)G_calloc(R->nfiles, sizeof(unsigned int));
  290. /* Allocate memory for temporary storage of sorted values */
  291. new_semantic_labels = (char **)G_malloc(S->nbands * sizeof(char *));
  292. new_means = (double **)G_malloc(S->nsigs * sizeof(double *));
  293. // new_vars[S.sig[x]][band1][band1]
  294. new_vars = (double ***)G_malloc(S->nsigs * sizeof(double **));
  295. for (unsigned int c = S->nsigs; c--;) {
  296. new_means[c] = (double *)G_malloc(S->nbands * sizeof(double));
  297. new_vars[c] = (double **)G_malloc(S->nbands * sizeof(double *));
  298. for (unsigned int i = S->nbands; i--;)
  299. new_vars[c][i] = (double *)G_malloc(S->nbands * sizeof(double));
  300. }
  301. /* Obtain order of matching items */
  302. for (unsigned int j = R->nfiles; j--;) {
  303. for (unsigned int i = S->nbands; i--;) {
  304. if (S->semantic_labels[i] && group_semantic_labels[j] &&
  305. !strcmp(S->semantic_labels[i], group_semantic_labels[j])) {
  306. if (complete) {
  307. /* Reorder pointers to existing strings only */
  308. new_semantic_labels[j] = S->semantic_labels[i];
  309. new_order[i] = j;
  310. }
  311. /* Keep a track of matching items for error reporting */
  312. match1[i] = 1;
  313. match2[j] = 1;
  314. break;
  315. }
  316. }
  317. }
  318. /* Check for semantic label mismatch */
  319. mc1 = mc2 = 0;
  320. mismatches = (char **)G_malloc(2 * sizeof(char **));
  321. mismatches[0] = NULL;
  322. mismatches[1] = NULL;
  323. total = 1;
  324. for (unsigned int i = 0; i < S->nbands; i++) {
  325. if (!match1[i]) {
  326. if (S->semantic_labels[i])
  327. total = total + strlen(S->semantic_labels[i]);
  328. else
  329. total = total + 24;
  330. mismatches[0] = (char *)G_realloc(mismatches[0], total * sizeof(char *));
  331. if (mc1)
  332. strcat(mismatches[0], ",");
  333. else
  334. mismatches[0][0] = '\0';
  335. if (S->semantic_labels[i])
  336. strcat(mismatches[0], S->semantic_labels[i]);
  337. else
  338. strcat(mismatches[0], "<semantic label missing>");
  339. mc1++;
  340. total = total + 1;
  341. }
  342. }
  343. total = 1;
  344. for (unsigned int j = 0; j < R->nfiles; j++) {
  345. if (!match2[j]) {
  346. if (group_semantic_labels[j])
  347. total = total + strlen(group_semantic_labels[j]);
  348. else
  349. total = total + 24;
  350. mismatches[1] = (char *)G_realloc(mismatches[1], total * sizeof(char *));
  351. if (mc2)
  352. strcat(mismatches[1], ",");
  353. else
  354. mismatches[1][0] = '\0';
  355. if (group_semantic_labels[j])
  356. strcat(mismatches[1], group_semantic_labels[j]);
  357. else
  358. strcat(mismatches[1], "<semantic label missing>");
  359. mc2++;
  360. total = total + 1;
  361. }
  362. }
  363. /* Swap var matrix values in each of classes */
  364. if (!mc1 && !mc2) {
  365. for (unsigned int c = S->nsigs; c--;) {
  366. for (unsigned int b1 = 0; b1 < S->nbands; b1++) {
  367. new_means[c][new_order[b1]] = S->sig[c].mean[b1];
  368. for (unsigned int b2 = 0; b2 <= b1; b2++) {
  369. if (new_order[b1] > new_order[b2]) {
  370. new_vars[c][new_order[b1]][new_order[b2]] = S->sig[c].var[b1][b2];
  371. }
  372. else {
  373. new_vars[c][new_order[b2]][new_order[b1]] = S->sig[c].var[b1][b2];
  374. }
  375. }
  376. }
  377. }
  378. /* Replace values in struct with ordered ones */
  379. memcpy(S->semantic_labels, new_semantic_labels, S->nbands * sizeof(char **));
  380. for (unsigned int c = S->nsigs; c--;) {
  381. memcpy(S->sig[c].mean, new_means[c], S->nbands * sizeof(double));
  382. for (unsigned int i = S->nbands; i--;)
  383. memcpy(S->sig[c].var[i], new_vars[c][i], S->nbands * sizeof(double));
  384. }
  385. }
  386. /* Clean up */
  387. for (unsigned int j = R->nfiles; j--;)
  388. free(group_semantic_labels[j]);
  389. free(group_semantic_labels);
  390. free(new_order);
  391. free(match1);
  392. free(match2);
  393. free(new_semantic_labels);
  394. for (unsigned int c = S->nsigs; c--;) {
  395. free(new_means[c]);
  396. for (unsigned int i = S->nbands; i--;)
  397. free(new_vars[c][i]);
  398. free(new_vars[c]);
  399. }
  400. free(new_means);
  401. free(new_vars);
  402. if (mc1 || mc2) {
  403. return mismatches;
  404. }
  405. free(mismatches);
  406. return NULL;
  407. }