GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
histogram.c
Go to the documentation of this file.
1 #include <stdlib.h>
2 
3 #include <grass/gis.h>
4 #include <grass/raster.h>
5 #include <grass/glocale.h>
6 
7 #define LIST struct Histogram_list
8 
9 static FILE *fopen_histogram_new(const char *);
10 static int cmp(const void *, const void *);
11 static int cmp_count(const void *, const void *);
12 
13 
14 /*!
15  * \brief initializes the histogram structure
16  *
17  * initializes the histogram structure for calls to Rast_set_histogram()
18  * and Rast_add_histogram()
19  * \param histogram
20  * \return
21  */
22 
23 void Rast_init_histogram(struct Histogram *histogram)
24 {
25  histogram->num = 0;
26  histogram->list = NULL;
27 }
28 
29 
30 /*!
31  * \brief read the histogram information
32  *
33  * Reads the histogram information associated with map layer "map"
34  * in mapset "mapset" into the structure "histogram".
35  *
36  * note: a warning message is printed if the file is missing or incorrect
37  * \param name: name of map
38  * \param mapset: mapset that map belongs to
39  * \param histogram: struct for histogram
40  * \return 1 if successful,
41  * 0 if no histogram file,
42  */
43 
44 int Rast_read_histogram(const char *name, const char *mapset,
45  struct Histogram *histogram)
46 {
47  FILE *fd = NULL;
48  long cat;
49  long count;
50  char buf[200];
51 
52  Rast_init_histogram(histogram);
53 
54  if (!G_find_file2_misc("cell_misc", "histogram", name, mapset)) {
55  G_warning(_("Histogram for [%s in %s] missing (run r.support)"), name,
56  mapset);
57  return 0;
58  }
59 
60  fd = G_fopen_old_misc("cell_misc", "histogram", name, mapset);
61  if (!fd)
62  G_fatal_error(_("Can't read histogram for [%s in %s]"), name, mapset);
63 
64  while (fgets(buf, sizeof buf, fd)) {
65  if (sscanf(buf, "%ld:%ld", &cat, &count) != 2)
66  G_fatal_error(_("Invalid histogram file for [%s in %s]"),
67  name, mapset);
68  Rast_extend_histogram((CELL) cat, count, histogram);
69  }
70  fclose(fd);
71 
72  if (histogram->num == 0)
73  G_fatal_error(_("Invalid histogram file for [%s in %s]"), name, mapset);
74 
75  Rast_sort_histogram(histogram);
76 
77  return 1;
78 }
79 
80 
81 /*!
82  * \brief Writes the histogram information
83  *
84  * Writes the histogram information associated with map layer "name"
85  * \param name: name of map
86  * \param histogram: struct for histogram
87  * \return void
88  */
89 
90 void Rast_write_histogram(const char *name, const struct Histogram *histogram)
91 {
92  FILE *fp;
93  int n;
94  LIST *list;
95 
96  fp = fopen_histogram_new(name);
97 
98  list = histogram->list;
99  for (n = 0; n < histogram->num; n++) {
100  if (list[n].count)
101  fprintf(fp, "%ld:%ld\n", (long)list[n].cat, list[n].count);
102  }
103 
104  fclose(fp);
105 }
106 
107 
108 /*!
109  * \brief Writes the histogram based on cell statistics to file
110  *
111  * \param name: name of map
112  * \param statf: cell statistics
113  * \return void
114  */
115 
116 void Rast_write_histogram_cs(const char *name, struct Cell_stats *statf)
117 {
118  FILE *fp;
119  CELL cat;
120  long count;
121 
122  fp = fopen_histogram_new(name);
123 
124  Rast_rewind_cell_stats(statf);
125  while (Rast_next_cell_stat(&cat, &count, statf)) {
126  if (count > 0)
127  fprintf(fp, "%ld:%ld\n", (long)cat, count);
128  }
129 
130  fclose(fp);
131 }
132 
133 
134 /*!
135  * \brief Creates histogram based on cell statistics
136  *
137  * \param statf: cell statistics
138  * \param histogram: raster histogram
139  * \return
140  */
142  struct Histogram *histogram)
143 {
144  CELL cat;
145  long count;
146 
147  Rast_init_histogram(histogram);
148  Rast_rewind_cell_stats(statf);
149  while (Rast_next_cell_stat(&cat, &count, statf))
150  Rast_add_histogram(cat, count, histogram);
151 
152  Rast_sort_histogram(histogram);
153 }
154 
155 
156 /*!
157  * \brief Sorts the histogram in ascending order by counts then category
158  *
159  * Sorts the histogram in ascending order by counts then category.
160  * No combining is done.
161  * \param histogram: struct for histogram
162  * \return 1 if successful,
163  * -1 on fail
164  */
165 int Rast_get_histogram_num(const struct Histogram *histogram)
166 {
167  return histogram->num;
168 }
169 
170 
171 /*!
172  * \brief Returns cat for the nth element in the histogram
173  *
174  * Returns cat for the nth element in the histogram
175  * \param histogram: struct for histogram
176  * \return CELL
177  */
178 CELL Rast_get_histogram_cat(int n, const struct Histogram * histogram)
179 {
180  if (n < 0 || n >= histogram->num)
181  return 0;
182 
183  return histogram->list[n].cat;
184 }
185 
186 
187 /*!
188  * \brief Returns count for the nth element in the histogram
189  *
190  * Returns count for the nth element in the histogram
191  * \param n: nth element
192  * \param histogram: struct for histogram
193  * \return count
194  */
195 long Rast_get_histogram_count(int n, const struct Histogram *histogram)
196 {
197  if (n < 0 || n >= histogram->num)
198  return 0;
199 
200  return histogram->list[n].count;
201 }
202 
203 
204 /*!
205  * \brief Frees memory allocated for the histogram
206  *
207  * frees the memory allocated for the histogram
208  * \param histogram: struct for histogram
209  * \return
210  */
211 void Rast_free_histogram(struct Histogram *histogram)
212 {
213  if (histogram->num > 0)
214  G_free(histogram->list);
215  histogram->num = 0;
216  histogram->list = NULL;
217 }
218 
219 /*!
220  * \brief Sorts the histogram
221  *
222  * Sorts the histogram in ascending order by category,
223  * combining (by adding) elements that have the same category.
224  * \param histogram: struct for histogram
225  * \return 0 if successful,
226  * 1 on fail
227  */
228 int Rast_sort_histogram(struct Histogram *histogram)
229 {
230  int a, b, n;
231  LIST *list;
232 
233  /* if histogram only has 1 entry, nothing to do */
234  if ((n = histogram->num) <= 1)
235  return 1;
236 
237  list = histogram->list;
238 
239  /* quick check to see if sorting needed */
240  for (a = 1; a < n; a++)
241  if (list[a - 1].cat >= list[a].cat)
242  break;
243  if (a >= n)
244  return 1;
245 
246  /* sort */
247  qsort(list, n, sizeof(LIST), &cmp);
248 
249  /* sum duplicate entries */
250  for (a = 0, b = 1; b < n; b++) {
251  if (list[a].cat != list[b].cat) {
252  a++;
253  list[a].count = list[b].count;
254  list[a].cat = list[b].cat;
255  }
256  else {
257  list[a].count += list[b].count;
258  }
259  }
260  histogram->num = a + 1;
261 
262  return 0;
263 }
264 
265 
266 static int cmp(const void *aa, const void *bb)
267 {
268  const LIST *a = aa, *b = bb;
269 
270  if (a->cat < b->cat)
271  return -1;
272 
273  if (a->cat > b->cat)
274  return 1;
275 
276  return 0;
277 }
278 
279 /*!
280  * \brief Sorts the histogram by counts
281  *
282  * Sorts the histogram in ascending order by counts then category.
283  * No combining is done.
284  * \param histogram: struct for histogram
285  * \return 0 if successful,
286  * 1 on fail
287  */
289 {
290  int n;
291  LIST *list;
292 
293  /* if histogram only has 1 entry, nothing to do */
294  if ((n = histogram->num) <= 1)
295  return 1;
296 
297  list = histogram->list;
298 
299  /* sort */
300  qsort(list, n, sizeof(LIST), &cmp_count);
301 
302  return 0;
303 }
304 
305 
306 static int cmp_count(const void *aa, const void *bb)
307 {
308  const LIST *a = aa, *b = bb;
309 
310  if (a->count < b->count)
311  return -1;
312 
313  if (a->count > b->count)
314  return 1;
315 
316  if (a->cat < b->cat)
317  return -1;
318 
319  if (a->cat > b->cat)
320  return 1;
321 
322  return 0;
323 }
324 
325 static FILE *fopen_histogram_new(const char *name)
326 {
327  FILE *fp;
328 
329  fp = G_fopen_new_misc("cell_misc", "histogram", name);
330  if (!fp)
331  G_fatal_error(_("Unable to create histogram file for <%s>"), name);
332 
333  return fp;
334 }
335 
336 /*!
337  * \brief Removes the histogram
338  *
339  * Removes the histogram information associated with map layer "name"
340  * \param name: name of map
341  * \return
342  */
343 
344 void Rast_remove_histogram(const char *name)
345 {
346  G_remove_misc("cell_misc", "histogram", name);
347 }
348 
349 
350 /*!
351  * \brief adds count to the histogram value for cat
352  *
353  * adds count to the histogram value for cat
354  * \param cat: category
355  * \param count
356  * \param histogram: struct for histogram
357  * \return 0 if successful,
358  * 1 on fail
359  */
360 int Rast_add_histogram(CELL cat, long count, struct Histogram *histogram)
361 {
362  int i;
363 
364  for (i = 0; i < histogram->num; i++) {
365  if (histogram->list[i].cat == cat) {
366  histogram->list[i].count += count;
367  return 1;
368  }
369  }
370  Rast_extend_histogram(cat, count, histogram);
371 
372  return 0;
373 }
374 
375 
376 /*!
377  * \brief sets the histogram value for cat to count
378  *
379  * sets the histogram value for cat to count
380  * \param cat: category
381  * \param count
382  * \param histogram: struct for histogram
383  * \return 0 if successful,
384  * 1 on fail
385  */
386 int Rast_set_histogram(CELL cat, long count, struct Histogram *histogram)
387 {
388  int i;
389 
390  for (i = 0; i < histogram->num; i++) {
391  if (histogram->list[i].cat == cat) {
392  histogram->list[i].count = count;
393  return 1;
394  }
395  }
396  Rast_extend_histogram(cat, count, histogram);
397 
398  return 0;
399 }
400 
401 
402 /*!
403  * \brief Extends histogram struct to accommodate a new value
404  *
405  * \param cat: category
406  * \param count
407  * \param histogram: struct for histogram
408  * \return
409  */
410 void Rast_extend_histogram(CELL cat, long count, struct Histogram *histogram)
411 {
412  histogram->num++;
413  histogram->list =
414  (LIST *) G_realloc(histogram->list, histogram->num * sizeof(LIST));
415  histogram->list[histogram->num - 1].cat = cat;
416  histogram->list[histogram->num - 1].count = count;
417 }
418 
419 
420 /*!
421  * \brief Zero out histogram struct
422  *
423  * \param histogram: struct for histogram
424  * \return
425  */
426 void Rast_zero_histogram(struct Histogram *histogram)
427 {
428  int i;
429 
430  for (i = 0; i < histogram->num; i++)
431  histogram->list[i].count = 0;
432 }
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void Rast_write_histogram_cs(const char *name, struct Cell_stats *statf)
Writes the histogram based on cell statistics to file.
Definition: histogram.c:116
int Rast_next_cell_stat(CELL *, long *, struct Cell_stats *)
Retrieve sorted cell stats.
Definition: cell_stats.c:314
int Rast_read_histogram(const char *name, const char *mapset, struct Histogram *histogram)
read the histogram information
Definition: histogram.c:44
int Rast_rewind_cell_stats(struct Cell_stats *)
Reset/rewind cell stats.
Definition: cell_stats.c:250
CELL Rast_get_histogram_cat(int n, const struct Histogram *histogram)
Returns cat for the nth element in the histogram.
Definition: histogram.c:178
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:149
int count
int Rast_sort_histogram(struct Histogram *histogram)
Sorts the histogram.
Definition: histogram.c:228
void Rast_remove_histogram(const char *name)
Removes the histogram.
Definition: histogram.c:344
#define NULL
Definition: ccmath.h:32
void Rast_make_histogram_cs(struct Cell_stats *statf, struct Histogram *histogram)
Creates histogram based on cell statistics.
Definition: histogram.c:141
int G_remove_misc(const char *, const char *, const char *)
Remove a database misc file.
Definition: remove.c:65
int Rast_sort_histogram_by_count(struct Histogram *histogram)
Sorts the histogram by counts.
Definition: histogram.c:288
#define LIST
Definition: histogram.c:7
double b
Definition: r_raster.c:39
struct list * list
Definition: read_list.c:24
int Rast_add_histogram(CELL cat, long count, struct Histogram *histogram)
adds count to the histogram value for cat
Definition: histogram.c:360
FILE * G_fopen_old_misc(const char *, const char *, const char *, const char *)
open a database misc file for reading
Definition: open_misc.c:210
void Rast_init_histogram(struct Histogram *histogram)
initializes the histogram structure
Definition: histogram.c:23
void Rast_extend_histogram(CELL cat, long count, struct Histogram *histogram)
Extends histogram struct to accommodate a new value.
Definition: histogram.c:410
void Rast_free_histogram(struct Histogram *histogram)
Frees memory allocated for the histogram.
Definition: histogram.c:211
int Rast_set_histogram(CELL cat, long count, struct Histogram *histogram)
sets the histogram value for cat to count
Definition: histogram.c:386
struct Histogram::Histogram_list * list
const char * G_find_file2_misc(const char *, const char *, const char *, const char *)
Searches for a misc file from the mapset search list or in a specified mapset. (look but don&#39;t touch)...
Definition: find_file.c:270
FILE * G_fopen_new_misc(const char *, const char *, const char *)
open a new database misc file
Definition: open_misc.c:182
void Rast_write_histogram(const char *name, const struct Histogram *histogram)
Writes the histogram information.
Definition: histogram.c:90
void G_warning(const char *,...) __attribute__((format(printf
int CELL
Definition: gis.h:613
#define G_realloc(p, n)
Definition: defs/gis.h:114
#define _(str)
Definition: glocale.h:10
void Rast_zero_histogram(struct Histogram *histogram)
Zero out histogram struct.
Definition: histogram.c:426
int Rast_get_histogram_num(const struct Histogram *histogram)
Sorts the histogram in ascending order by counts then category.
Definition: histogram.c:165
long Rast_get_histogram_count(int n, const struct Histogram *histogram)
Returns count for the nth element in the histogram.
Definition: histogram.c:195
int num
Definition: raster.h:209
const char * name
Definition: named_colr.c:7