PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ rt_band_get_summary_stats()

rt_bandstats rt_band_get_summary_stats ( rt_band  band,
int  exclude_nodata_value,
double  sample,
int  inc_vals,
uint64_t *  cK,
double *  cM,
double *  cQ 
)

Compute summary statistics for a band.

Parameters
band: the band to query for summary stats
exclude_nodata_value: if non-zero, ignore nodata values
sample: percentage of pixels to sample
inc_vals: flag to include values in return struct
cK: number of pixels counted thus far in coverage
cM: M component of 1-pass stddev for coverage
cQ: Q component of 1-pass stddev for coverage
Returns
the summary statistics for a band or NULL

Definition at line 111 of file rt_statistics.c.

115 {
116 uint32_t x = 0;
117 int64_t y = 0;
118 uint32_t z = 0;
119 uint32_t offset = 0;
120 uint32_t diff = 0;
121 int rtn;
122 int hasnodata = FALSE;
123 double nodata = 0;
124 double *values = NULL;
125 double value;
126 int isnodata = 0;
127 rt_bandstats stats = NULL;
128
129 uint32_t do_sample = 0;
130 uint32_t sample_size = 0;
131 uint32_t sample_per = 0;
132 uint32_t sample_int = 0;
133 uint32_t i = 0;
134 uint32_t j = 0;
135 double sum = 0;
136 uint32_t k = 0;
137 double M = 0;
138 double Q = 0;
139
140#if POSTGIS_DEBUG_LEVEL > 0
141 clock_t start, stop;
142 double elapsed = 0;
143#endif
144
145 RASTER_DEBUG(3, "starting");
146#if POSTGIS_DEBUG_LEVEL > 0
147 start = clock();
148#endif
149
150 assert(NULL != band);
151
152 /* band is empty (width < 1 || height < 1) */
153 if (band->width < 1 || band->height < 1) {
154 stats = (rt_bandstats) rtalloc(sizeof(struct rt_bandstats_t));
155 if (NULL == stats) {
156 rterror("rt_band_get_summary_stats: Could not allocate memory for stats");
157 return NULL;
158 }
159
160 rtwarn("Band is empty as width and/or height is 0");
161
162 stats->sample = 1;
163 stats->sorted = 0;
164 stats->values = NULL;
165 stats->count = 0;
166 stats->min = stats->max = 0;
167 stats->sum = 0;
168 stats->mean = 0;
169 stats->stddev = -1;
170
171 return stats;
172 }
173
174 hasnodata = rt_band_get_hasnodata_flag(band);
175 if (hasnodata != FALSE)
176 rt_band_get_nodata(band, &nodata);
177 else
178 exclude_nodata_value = 0;
179
180 RASTER_DEBUGF(3, "nodata = %f", nodata);
181 RASTER_DEBUGF(3, "hasnodata = %d", hasnodata);
182 RASTER_DEBUGF(3, "exclude_nodata_value = %d", exclude_nodata_value);
183
184 /* entire band is nodata */
185 if (rt_band_get_isnodata_flag(band) != FALSE) {
186 stats = (rt_bandstats) rtalloc(sizeof(struct rt_bandstats_t));
187 if (NULL == stats) {
188 rterror("rt_band_get_summary_stats: Could not allocate memory for stats");
189 return NULL;
190 }
191
192 stats->sample = 1;
193 stats->sorted = 0;
194 stats->values = NULL;
195
196 if (exclude_nodata_value) {
197 rtwarn("All pixels of band have the NODATA value");
198
199 stats->count = 0;
200 stats->min = stats->max = 0;
201 stats->sum = 0;
202 stats->mean = 0;
203 stats->stddev = -1;
204 }
205 else {
206 stats->count = band->width * band->height;
207 stats->min = stats->max = nodata;
208 stats->sum = stats->count * nodata;
209 stats->mean = nodata;
210 stats->stddev = 0;
211 }
212
213 return stats;
214 }
215
216 /* clamp percentage */
217 if (
218 (sample < 0 || FLT_EQ(sample, 0.0)) ||
219 (sample > 1 || FLT_EQ(sample, 1.0))
220 ) {
221 do_sample = 0;
222 sample = 1;
223 }
224 else
225 do_sample = 1;
226 RASTER_DEBUGF(3, "do_sample = %d", do_sample);
227
228 /* sample all pixels */
229 if (!do_sample) {
230 sample_size = band->width * band->height;
231 sample_per = band->height;
232 }
233 /*
234 randomly sample a percentage of available pixels
235 sampling method is known as
236 "systematic random sample without replacement"
237 */
238 else {
239 sample_size = round((band->width * band->height) * sample);
240 sample_per = round(sample_size / band->width);
241 if (sample_per < 1)
242 sample_per = 1;
243 sample_int = round(band->height / sample_per);
244 srand(time(NULL));
245 }
246
247 RASTER_DEBUGF(3, "sampling %d of %d available pixels w/ %d per set"
248 , sample_size, (band->width * band->height), sample_per);
249
250 if (inc_vals) {
251 values = rtalloc(sizeof(double) * sample_size);
252 if (NULL == values) {
253 rtwarn("Could not allocate memory for values");
254 inc_vals = 0;
255 }
256 }
257
258 /* initialize stats */
259 stats = (rt_bandstats) rtalloc(sizeof(struct rt_bandstats_t));
260 if (NULL == stats) {
261 rterror("rt_band_get_summary_stats: Could not allocate memory for stats");
262 return NULL;
263 }
264 stats->sample = sample;
265 stats->count = 0;
266 stats->sum = 0;
267 stats->mean = 0;
268 stats->stddev = -1;
269 stats->min = stats->max = 0;
270 stats->values = NULL;
271 stats->sorted = 0;
272
273 for (x = 0, j = 0, k = 0; x < band->width; x++) {
274 y = -1;
275 diff = 0;
276
277 for (i = 0, z = 0; i < sample_per; i++) {
278 if (!do_sample)
279 y = i;
280 else {
281 offset = (rand() % sample_int) + 1;
282 y += diff + offset;
283 diff = sample_int - offset;
284 }
285 RASTER_DEBUGF(5, "(x, y, z) = (%u, %lld, %u)", x, y, z);
286 if (y >= band->height || z > sample_per) break;
287
288 rtn = rt_band_get_pixel(band, x, y, &value, &isnodata);
289
290 j++;
291 if (rtn == ES_NONE && (!exclude_nodata_value || (exclude_nodata_value && !isnodata))) {
292
293 /* inc_vals set, collect pixel values */
294 if (inc_vals) values[k] = value;
295
296 /* average */
297 k++;
298 sum += value;
299
300 /*
301 one-pass standard deviation
302 http://www.eecs.berkeley.edu/~mhoemmen/cs194/Tutorials/variance.pdf
303 */
304 if (k == 1) {
305 Q = 0;
306 M = value;
307 }
308 else {
309 Q += (((k - 1) * pow(value - M, 2)) / k);
310 M += ((value - M ) / k);
311 }
312
313 /* coverage one-pass standard deviation */
314 if (NULL != cK) {
315 (*cK)++;
316 if (*cK == 1) {
317 *cQ = 0;
318 *cM = value;
319 }
320 else {
321 *cQ += (((*cK - 1) * pow(value - *cM, 2)) / *cK);
322 *cM += ((value - *cM ) / *cK);
323 }
324 }
325
326 /* min/max */
327 if (stats->count < 1) {
328 stats->count = 1;
329 stats->min = stats->max = value;
330 }
331 else {
332 if (value < stats->min)
333 stats->min = value;
334 if (value > stats->max)
335 stats->max = value;
336 }
337
338 }
339
340 z++;
341 }
342 }
343
344 RASTER_DEBUG(3, "sampling complete");
345
346 stats->count = k;
347 if (k > 0) {
348 if (inc_vals) {
349 /* free unused memory */
350 if (sample_size != k) {
351 values = rtrealloc(values, k * sizeof(double));
352 }
353
354 stats->values = values;
355 }
356
357 stats->sum = sum;
358 stats->mean = sum / k;
359
360 /* standard deviation */
361 if (!do_sample)
362 stats->stddev = sqrt(Q / k);
363 /* sample deviation */
364 else {
365 if (k < 2)
366 stats->stddev = -1;
367 else
368 stats->stddev = sqrt(Q / (k - 1));
369 }
370 }
371 /* inc_vals thus values allocated but not used */
372 else if (inc_vals)
373 rtdealloc(values);
374
375 /* if do_sample is one */
376 if (do_sample && k < 1)
377 rtwarn("All sampled pixels of band have the NODATA value");
378
379#if POSTGIS_DEBUG_LEVEL > 0
380 stop = clock();
381 elapsed = ((double) (stop - start)) / CLOCKS_PER_SEC;
382 RASTER_DEBUGF(3, "(time, count, mean, stddev, min, max) = (%0.4f, %d, %f, %f, %f, %f)",
383 elapsed, stats->count, stats->mean, stats->stddev, stats->min, stats->max);
384#endif
385
386 RASTER_DEBUG(3, "done");
387 return stats;
388}
#define FALSE
Definition dbfopen.c:72
void rterror(const char *fmt,...) __attribute__((format(printf
Wrappers used for reporting errors and info.
void * rtalloc(size_t size)
Wrappers used for managing memory.
Definition rt_context.c:191
#define RASTER_DEBUG(level, msg)
Definition librtcore.h:304
#define RASTER_DEBUGF(level, msg,...)
Definition librtcore.h:308
void void void rtwarn(const char *fmt,...) __attribute__((format(printf
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
Definition rt_band.c:833
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
Definition rt_band.c:1551
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
Definition rt_band.c:873
#define FLT_EQ(x, y)
Definition librtcore.h:2436
struct rt_bandstats_t * rt_bandstats
Definition librtcore.h:151
@ ES_NONE
Definition librtcore.h:182
void * rtrealloc(void *mem, size_t size)
Definition rt_context.c:199
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Definition rt_band.c:2067
void rtdealloc(void *mem)
Definition rt_context.c:206
int value
Definition genraster.py:62
uint32_t count
Definition librtcore.h:2562
double * values
Definition librtcore.h:2570

References rt_bandstats_t::count, ES_NONE, FALSE, FLT_EQ, rt_bandstats_t::max, rt_bandstats_t::mean, rt_bandstats_t::min, RASTER_DEBUG, RASTER_DEBUGF, rt_band_get_hasnodata_flag(), rt_band_get_isnodata_flag(), rt_band_get_nodata(), rt_band_get_pixel(), rtalloc(), rtdealloc(), rterror(), rtrealloc(), rtwarn(), rt_bandstats_t::sample, rt_bandstats_t::sorted, rt_bandstats_t::stddev, rt_bandstats_t::sum, and rt_bandstats_t::values.

Referenced by RASTER_colorMap(), RASTER_histogram(), RASTER_quantile(), RASTER_summaryStats(), RASTER_summaryStats_transfn(), RASTER_summaryStatsCoverage(), test_band_stats(), and test_gdal_warp_preserves_data().

Here is the call graph for this function:
Here is the caller graph for this function: