37 #define SWAP(x, y) { double t; t = x; x = y; y = t; } 38 #define ORDER(x, y) if (x > y) SWAP(x, y) 40 static double pivot(
double *left,
double *right) {
44 m = *(left + (right - left) / 2);
57 for (p = left + 1; p <= right; ++p) {
59 return (*p < *left) ? *left : *p;
67 while (left <= right) {
68 while (*left < pivot) ++left;
69 while (*right >= pivot) --right;
81 static void quicksort(
double *left,
double *right) {
82 double p =
pivot(left, right);
112 int exclude_nodata_value,
double sample,
int inc_vals,
113 uint64_t *cK,
double *cM,
double *cQ
121 int hasnodata =
FALSE;
123 double *values = NULL;
139 #if POSTGIS_DEBUG_LEVEL > 0 145 #if POSTGIS_DEBUG_LEVEL > 0 149 assert(NULL != band);
155 rterror(
"rt_band_get_summary_stats: Could not allocate memory for stats");
159 rtwarn(
"Band is empty as width and/or height is 0");
165 stats->
min = stats->
max = 0;
174 if (hasnodata !=
FALSE)
177 exclude_nodata_value = 0;
181 RASTER_DEBUGF(3,
"exclude_nodata_value = %d", exclude_nodata_value);
187 rterror(
"rt_band_get_summary_stats: Could not allocate memory for stats");
195 if (exclude_nodata_value) {
196 rtwarn(
"All pixels of band have the NODATA value");
199 stats->
min = stats->
max = 0;
206 stats->
min = stats->
max = nodata;
208 stats->
mean = nodata;
217 (sample < 0 ||
FLT_EQ(sample, 0.0)) ||
218 (sample > 1 ||
FLT_EQ(sample, 1.0))
230 sample_per = band->
height;
238 sample_size = round((band->
width * band->
height) * sample);
239 sample_per = round(sample_size / band->
width);
242 sample_int = round(band->
height / sample_per);
246 RASTER_DEBUGF(3,
"sampling %d of %d available pixels w/ %d per set" 247 , sample_size, (band->
width * band->
height), sample_per);
250 values =
rtalloc(
sizeof(
double) * sample_size);
251 if (NULL == values) {
252 rtwarn(
"Could not allocate memory for values");
260 rterror(
"rt_band_get_summary_stats: Could not allocate memory for stats");
268 stats->
min = stats->
max = 0;
272 for (x = 0, j = 0, k = 0; x < band->
width; x++) {
276 for (i = 0, z = 0; i < sample_per; i++) {
280 offset = (rand() % sample_int) + 1;
282 diff = sample_int - offset;
285 if (y >= band->
height || z > sample_per)
break;
290 if (rtn ==
ES_NONE && (!exclude_nodata_value || (exclude_nodata_value && !isnodata))) {
293 if (inc_vals) values[k] =
value;
308 Q += (((k - 1) * pow(value - M, 2)) / k);
309 M += ((value - M ) / k);
320 *cQ += (((*cK - 1) * pow(value - *cM, 2)) / *cK);
321 *cM += ((value - *cM ) / *cK);
326 if (stats->
count < 1) {
331 if (value < stats->min)
333 if (value > stats->
max)
349 if (sample_size != k) {
350 values =
rtrealloc(values, k *
sizeof(
double));
357 stats->
mean = sum / k;
361 stats->
stddev = sqrt(Q / k);
367 stats->
stddev = sqrt(Q / (k - 1));
375 if (do_sample && k < 1)
376 rtwarn(
"All sampled pixels of band have the NODATA value");
378 #if POSTGIS_DEBUG_LEVEL > 0 380 elapsed = ((double) (stop - start)) / CLOCKS_PER_SEC;
381 RASTER_DEBUGF(3,
"(time, count, mean, stddev, min, max) = (%0.4f, %d, %f, %f, %f, %f)",
414 int bin_count,
double *bin_width,
int bin_width_count,
415 int right,
double min,
double max,
428 #if POSTGIS_DEBUG_LEVEL > 0 434 #if POSTGIS_DEBUG_LEVEL > 0 438 assert(NULL != stats);
439 assert(NULL != rtn_count);
442 rterror(
"rt_util_get_histogram: rt_bandstats object has no value");
447 if (NULL != bin_width && bin_width_count > 0) {
448 for (i = 0; i < bin_width_count; i++) {
449 if (bin_width[i] < 0 ||
FLT_EQ(bin_width[i], 0.0)) {
450 rterror(
"rt_util_get_histogram: bin_width element is less than or equal to zero");
471 if (bin_count <= 0) {
479 if (stats->
count < 30)
480 bin_count = ceil(sqrt(stats->
count));
483 bin_count = ceil(log2((
double) stats->
count) + 1.);
486 if (bin_width_count > 0 && NULL != bin_width) {
488 if (bin_width_count > bin_count)
489 bin_count = bin_width_count;
490 else if (bin_width_count > 1) {
492 for (i = 0; i < bin_width_count; i++) tmp += bin_width[i];
493 bin_count = ceil((qmax - qmin) / tmp) * bin_width_count;
496 bin_count = ceil((qmax - qmin) / bin_width[0]);
505 if (
FLT_EQ(qmax, qmin)) bin_count = 1;
513 rterror(
"rt_util_get_histogram: Could not allocate memory for histogram");
523 *rtn_count = bin_count;
528 if (bin_width_count == 0) {
532 if (NULL == bin_width) {
533 bin_width =
rtalloc(
sizeof(
double));
534 if (NULL == bin_width) {
535 rterror(
"rt_util_get_histogram: Could not allocate memory for bin widths");
541 bin_width[0] = (qmax - qmin) / bin_count;
547 rterror(
"rt_util_get_histogram: Could not allocate memory for histogram");
555 for (i = 0; i < bin_count;) {
556 for (j = 0; j < bin_width_count; j++) {
581 bins[bin_count - 1].
inc_max = 1;
584 if (bins[bin_count - 1].max < qmax)
585 bins[bin_count - 1].
max = qmax;
588 bins[bin_count - 1].
inc_min = 1;
591 if (bins[bin_count - 1].min > qmin)
592 bins[bin_count - 1].
min = qmin;
596 for (i = 0; i < stats->
count; i++) {
601 for (j = 0; j < bin_count; j++) {
603 (!bins[j].inc_max && value < bins[j].max) || (
605 (value < bins[j].max) ||
606 FLT_EQ(value, bins[j].max)
618 for (j = 0; j < bin_count; j++) {
620 (!bins[j].inc_min && value > bins[j].min) || (
622 (value > bins[j].min) ||
623 FLT_EQ(value, bins[j].min)
635 for (i = 0; i < bin_count; i++) {
639 #if POSTGIS_DEBUG_LEVEL > 0 641 elapsed = ((double) (stop - start)) / CLOCKS_PER_SEC;
644 for (j = 0; j < bin_count; j++) {
645 RASTER_DEBUGF(5,
"(min, max, inc_min, inc_max, count, sum, percent) = (%f, %f, %d, %d, %d, %d, %f)",
646 bins[j].min, bins[j].max, bins[j].inc_min, bins[j].inc_max, bins[j].
count, sum, bins[j].percent);
651 *rtn_count = bin_count;
674 double *quantiles,
int quantiles_count,
678 int init_quantiles = 0;
683 #if POSTGIS_DEBUG_LEVEL > 0 689 #if POSTGIS_DEBUG_LEVEL > 0 693 assert(NULL != stats);
694 assert(NULL != rtn_count);
697 rterror(
"rt_band_get_quantiles: rt_bandstats object has no value");
702 if (NULL == quantiles) {
704 if (quantiles_count < 2)
707 quantiles =
rtalloc(
sizeof(
double) * quantiles_count);
709 if (NULL == quantiles) {
710 rterror(
"rt_band_get_quantiles: Could not allocate memory for quantile input");
715 for (i = 0; i <= quantiles_count; i++)
716 quantiles[i] = ((
double) i) / quantiles_count;
721 for (i = 0; i < quantiles_count; i++) {
722 if (quantiles[i] < 0. || quantiles[i] > 1.) {
723 rterror(
"rt_band_get_quantiles: Quantile value not between 0 and 1");
724 if (init_quantiles)
rtdealloc(quantiles);
728 quicksort(quantiles, quantiles + quantiles_count - 1);
733 rterror(
"rt_band_get_quantiles: Could not allocate memory for quantile output");
734 if (init_quantiles)
rtdealloc(quantiles);
750 for (i = 0; i < quantiles_count; i++) {
753 h = ((stats->
count - 1.) * quantiles[i]) + 1.;
764 #if POSTGIS_DEBUG_LEVEL > 0 766 elapsed = ((double) (stop - start)) / CLOCKS_PER_SEC;
770 *rtn_count = quantiles_count;
771 if (init_quantiles)
rtdealloc(quantiles);
787 if (NULL != element->
next)
803 if (NULL == element) {
806 if (NULL == qle)
return NULL;
814 if (NULL != idx) *idx = 0;
817 else if (value > element->
value) {
818 if (NULL != idx) *idx += 1;
819 if (NULL != element->
next)
825 if (NULL == qle)
return NULL;
840 RASTER_DEBUGF(4,
"insert qle @ %p before current element", qle);
841 if (NULL == qle)
return NULL;
856 if (NULL == element)
return 0;
859 if (NULL == element->
prev && NULL != element->
next) {
863 else if (NULL != element->
prev && NULL == element->
next) {
867 else if (NULL != element->
prev && NULL != element->
next) {
882 if (NULL == *list)
return 0;
884 for (i = 0; i < list_count; i++) {
885 element = (*list)[i].head;
886 while (NULL != element->
next) {
901 if (qll->
tail == qle)
return;
949 if (value > (qll->
index[i]).element->value)
continue;
957 for (j = 1; j < i; j++) {
960 *index = (i - j) * 100;
1012 int exclude_nodata_value,
double sample,
1015 double *quantiles,
int quantiles_count,
1019 int init_quantiles = 0;
1050 assert(NULL != band);
1051 assert(cov_count > 1);
1052 assert(NULL != rtn_count);
1057 rterror(
"rt_band_get_summary_stats: Cannot get band data");
1062 exclude_nodata_value = 0;
1063 RASTER_DEBUGF(3,
"exclude_nodata_value = %d", exclude_nodata_value);
1066 if (NULL == *qlls) {
1068 if (NULL == quantiles) {
1070 if (quantiles_count < 2)
1071 quantiles_count = 5;
1073 quantiles =
rtalloc(
sizeof(
double) * quantiles_count);
1075 if (NULL == quantiles) {
1076 rterror(
"rt_band_get_quantiles_stream: Could not allocate memory for quantile input");
1081 for (i = 0; i <= quantiles_count; i++)
1082 quantiles[i] = ((
double) i) / quantiles_count;
1087 for (i = 0; i < quantiles_count; i++) {
1088 if (quantiles[i] < 0. || quantiles[i] > 1.) {
1089 rterror(
"rt_band_get_quantiles_stream: Quantile value not between 0 and 1");
1090 if (init_quantiles)
rtdealloc(quantiles);
1094 quicksort(quantiles, quantiles + quantiles_count - 1);
1097 *qlls_count = quantiles_count * 2;
1100 if (NULL == *qlls) {
1101 rterror(
"rt_band_get_quantiles_stream: Could not allocate memory for quantile output");
1102 if (init_quantiles)
rtdealloc(quantiles);
1106 j = (
uint32_t) floor(MAX_VALUES / 100.) + 1;
1107 for (i = 0; i < *qlls_count; i++) {
1108 qll = &((*qlls)[i]);
1109 qll->
quantile = quantiles[(i * quantiles_count) / *qlls_count];
1118 if (NULL == qll->
index) {
1119 rterror(
"rt_band_get_quantiles_stream: Could not allocate memory for quantile output");
1120 if (init_quantiles)
rtdealloc(quantiles);
1130 if (qll->
tau < 1) qll->
tau = 1;
1135 qll->
tau = cov_count - (*qlls)[i - 1].tau + 1;
1138 RASTER_DEBUGF(4,
"qll init: (algeq, quantile, count, tau, sum1, sum2) = (%d, %f, %d, %d, %d, %d)",
1143 if (init_quantiles)
rtdealloc(quantiles);
1148 (sample < 0 ||
FLT_EQ(sample, 0.0)) ||
1149 (sample > 1 ||
FLT_EQ(sample, 1.0))
1161 sample_per = band->
height;
1169 sample_size = round((band->
width * band->
height) * sample);
1170 sample_per = round(sample_size / band->
width);
1171 sample_int = round(band->
height / sample_per);
1174 RASTER_DEBUGF(3,
"sampling %d of %d available pixels w/ %d per set" 1175 , sample_size, (band->
width * band->
height), sample_per);
1177 for (x = 0, j = 0, k = 0; x < band->
width; x++) {
1183 RASTER_DEBUG(3,
"Skipping quantile calcuation as band is NODATA");
1187 for (i = 0, z = 0; i < sample_per; i++) {
1191 offset = (rand() % sample_int) + 1;
1193 diff = sample_int - offset;
1196 if (y >= band->
height || z > sample_per)
break;
1201 if (status ==
ES_NONE && (!exclude_nodata_value || (exclude_nodata_value && !isnodata))) {
1204 for (a = 0; a < *qlls_count; a++) {
1205 qll = &((*qlls)[a]);
1208 RASTER_DEBUGF(5,
"qll before: (algeq, quantile, count, tau, sum1, sum2) = (%d, %f, %d, %d, %d, %d)",
1214 if (NULL != qll->
head) {
1215 if (value < qll->head->value)
1229 if (NULL != qll->
head) {
1273 else if (qll->
count < MAX_VALUES) {
1285 if (NULL == qle)
return NULL;
1286 RASTER_DEBUGF(5,
"value added at index: %d => %f", idx, value);
1291 if (NULL == qle->
prev)
1294 if (NULL == qle->
next)
1305 RASTER_DEBUGF(5,
"qle, prev, next, head, tail = %p, %p, %p, %p, %p", qle, qle->
prev, qle->
next, qll->
head, qll->
tail);
1308 else if (qll->
algeq) {
1311 if (value < qll->head->value) {
1341 if (NULL == qle)
return NULL;
1342 RASTER_DEBUGF(5,
"value added at index: %d => %f", idx, value);
1347 if (NULL == qle->
prev)
1350 if (NULL == qle->
next)
1363 while (NULL != qle) {
1364 if (qle->
value < value) {
1411 if (NULL == qle)
return NULL;
1412 RASTER_DEBUGF(5,
"value added at index: %d => %f", idx, value);
1417 if (NULL == qle->
prev)
1420 if (NULL == qle->
next)
1433 while (NULL != qle) {
1434 if (qle->
value > value) {
1501 RASTER_DEBUGF(5,
"qll after: (algeq, quantile, count, tau, sum1, sum2) = (%d, %f, %d, %d, %d, %d)",
1508 RASTER_DEBUGF(5,
"skipping value at (x, y) = (%d, %d)", x, y);
1516 *rtn_count = *qlls_count / 2;
1518 if (NULL == rtn)
return NULL;
1521 for (i = 0, k = 0; i < *qlls_count; i++) {
1522 qll = &((*qlls)[i]);
1525 for (x = 0; x < k; x++) {
1531 if (exists)
continue;
1533 RASTER_DEBUGF(5,
"qll: (algeq, quantile, count, tau, sum1, sum2) = (%d, %f, %d, %d, %d, %d)",
1541 if (qll->
head == NULL || qll->
tail == NULL)
1552 for (j = i + 1; j < *qlls_count; j++) {
1555 RASTER_DEBUGF(5,
"qlls[%d]: (algeq, quantile, count, tau, sum1, sum2) = (%d, %f, %d, %d, %d, %d)",
1556 j, (*qlls)[j].algeq, (*qlls)[j].quantile, (*qlls)[j].
count, (*qlls)[j].tau, (*qlls)[j].sum1, (*qlls)[j].sum2);
1557 RASTER_DEBUGF(5,
"qlls[%d]: (head, tail) = (%p, %p)", j, (*qlls)[j].head, (*qlls)[j].tail);
1566 if ((*qlls)[j].algeq) {
1567 rtn[k].
value = ((qle->
value * qle->
count) + ((*qlls)[j].head->value * (*qlls)[j].head->count)) / (qle->
count + (*qlls)[j].head->count);
1568 RASTER_DEBUGF(5,
"qlls[%d].head: (value, count) = (%f, %d)", j, (*qlls)[j].head->value, (*qlls)[j].head->count);
1571 rtn[k].
value = ((qle->
value * qle->
count) + ((*qlls)[j].tail->value * (*qlls)[j].tail->count)) / (qle->
count + (*qlls)[j].tail->count);
1572 RASTER_DEBUGF(5,
"qlls[%d].tail: (value, count) = (%f, %d)", j, (*qlls)[j].tail->value, (*qlls)[j].tail->count);
1580 RASTER_DEBUGF(3,
"(quantile, value) = (%f, %f)\n\n", rtn[k].quantile, rtn[k].value);
1610 double *search_values,
uint32_t search_values_count,
double roundto,
1630 int vcnts_count = 0;
1631 int new_valuecount = 0;
1633 #if POSTGIS_DEBUG_LEVEL > 0 1634 clock_t start, stop;
1639 #if POSTGIS_DEBUG_LEVEL > 0 1643 assert(NULL != band);
1644 assert(NULL != rtn_count);
1648 rterror(
"rt_band_get_summary_stats: Cannot get band data");
1659 exclude_nodata_value = 0;
1663 RASTER_DEBUGF(3,
"exclude_nodata_value = %d", exclude_nodata_value);
1666 if (roundto < 0 ||
FLT_EQ(roundto, 0.0)) {
1671 else if (roundto < 1) {
1688 for (scale = 0; scale <= 20; scale++) {
1689 tmpd = roundto * pow(10, scale);
1690 if (
FLT_EQ((tmpd - ((
int) tmpd)), 0.0))
break;
1699 for (scale = 0; scale >= -20; scale--) {
1700 tmpd = roundto * pow(10, scale);
1701 if (tmpd < 1 ||
FLT_EQ(tmpd, 1.0)) {
1702 if (scale == 0) doround = 1;
1708 if (scale != 0 || doround)
1716 if (search_values_count > 0 && NULL != search_values) {
1718 if (NULL == vcnts) {
1719 rterror(
"rt_band_get_count_of_values: Could not allocate memory for value counts");
1724 for (i = 0; i < search_values_count; i++) {
1728 vcnts[i].
value = search_values[i];
1730 vcnts[i].
value =
ROUND(search_values[i], scale);
1735 search_values_count = 0;
1736 RASTER_DEBUGF(3,
"search_values_count = %d", search_values_count);
1740 if (exclude_nodata_value) {
1741 rtwarn(
"All pixels of band have the NODATA value");
1745 if (search_values_count > 0) {
1747 for (i = 0; i < search_values_count; i++) {
1751 tmpd =
ROUND(nodata, scale);
1757 if (NULL != rtn_total) *rtn_total = vcnts[i].
count;
1761 *rtn_count = vcnts_count;
1766 if (NULL == vcnts) {
1767 rterror(
"rt_band_get_count_of_values: Could not allocate memory for value counts");
1772 vcnts->
value = nodata;
1774 if (NULL != rtn_total) *rtn_total = vcnts[i].
count;
1784 for (x = 0; x < band->
width; x++) {
1785 for (y = 0; y < band->
height; y++) {
1792 if (!exclude_nodata_value || (exclude_nodata_value && !isnodata)) {
1795 rpxlval =
ROUND(pxlval, scale);
1799 RASTER_DEBUGF(5,
"(pxlval, rpxlval) => (%0.6f, %0.6f)", pxlval, rpxlval);
1803 for (i = 0; i < vcnts_count; i++) {
1818 if (!new_valuecount || search_values_count > 0)
continue;
1822 if (NULL == vcnts) {
1823 rterror(
"rt_band_get_count_of_values: Could not allocate memory for value counts");
1828 vcnts[vcnts_count].
value = rpxlval;
1829 vcnts[vcnts_count].
count = 1;
1830 vcnts[vcnts_count].
percent = 0;
1837 #if POSTGIS_DEBUG_LEVEL > 0 1839 elapsed = ((double) (stop - start)) / CLOCKS_PER_SEC;
1843 for (i = 0; i < vcnts_count; i++) {
1849 if (NULL != rtn_total) *rtn_total = total;
1850 *rtn_count = vcnts_count;
static int quantile_llist_delete(struct quantile_llist_element *element)
struct quantile_llist_element * element
struct quantile_llist_element * prev
rt_quantile rt_band_get_quantiles(rt_bandstats stats, double *quantiles, int quantiles_count, uint32_t *rtn_count)
Compute the default set of or requested quantiles for a set of data the quantile formula used is same...
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.
static void quantile_llist_index_reset(struct quantile_llist *qll)
void rterror(const char *fmt,...)
Wrappers used for reporting errors and info.
void * rtalloc(size_t size)
Wrappers used for managing memory.
static struct quantile_llist_element * quantile_llist_index_search(struct quantile_llist *qll, double value, uint32_t *index)
void * rtrealloc(void *mem, size_t size)
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
struct quantile_llist_element * next
rt_histogram rt_band_get_histogram(rt_bandstats stats, int bin_count, double *bin_width, int bin_width_count, int right, double min, double max, uint32_t *rtn_count)
Count the distribution of data.
struct quantile_llist_element * tail
static void quicksort(double *left, double *right)
rt_valuecount rt_band_get_value_count(rt_band band, int exclude_nodata_value, double *search_values, uint32_t search_values_count, double roundto, uint32_t *rtn_total, uint32_t *rtn_count)
Count the number of times provided value(s) occur in the band.
void rtwarn(const char *fmt,...)
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
static double * partition(double *left, double *right, double pivot)
static void quantile_llist_index_delete(struct quantile_llist *qll, struct quantile_llist_element *qle)
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
void * rt_band_get_data(rt_band band)
Get pointer to raster band data.
#define RASTER_DEBUGF(level, msg,...)
static void quantile_llist_index_update(struct quantile_llist *qll, struct quantile_llist_element *qle, uint32_t idx)
struct rt_valuecount_t * rt_valuecount
static double pivot(double *left, double *right)
struct rt_bandstats_t * rt_bandstats
void rtdealloc(void *mem)
#define RASTER_DEBUG(level, msg)
This library is the generic raster handling section of PostGIS.
static struct quantile_llist_element * quantile_llist_insert(struct quantile_llist_element *element, double value, uint32_t *idx)
struct quantile_llist_index * index
int quantile_llist_destroy(struct quantile_llist **list, uint32_t list_count)
static struct quantile_llist_element * quantile_llist_search(struct quantile_llist_element *element, double needle)
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
struct quantile_llist_element * head
rt_quantile rt_band_get_quantiles_stream(rt_band band, int exclude_nodata_value, double sample, uint64_t cov_count, struct quantile_llist **qlls, uint32_t *qlls_count, double *quantiles, int quantiles_count, uint32_t *rtn_count)
Compute the default set of or requested quantiles for a coverage.