Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add Force() to force computation of histogram if not cached #63

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions godal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -791,11 +791,14 @@ size_t godalVSIRead(VSILFILE *f, void *buf, int len, char **errmsg) {
}

void godalRasterHistogram(cctx *ctx, GDALRasterBandH bnd, double *min, double *max, int *buckets,
unsigned long long **values, int bIncludeOutOfRange, int bApproxOK) {
unsigned long long **values, int bIncludeOutOfRange, int bApproxOK, int bForce) {
godalWrap(ctx);
CPLErr ret = CE_None;
if (*buckets == 0) {
ret=GDALGetDefaultHistogramEx(bnd,min,max,buckets,values,1,nullptr,nullptr);
ret=GDALGetDefaultHistogramEx(bnd,min,max,buckets,values,bForce,nullptr,nullptr);
if(ret == CE_Warning && ctx->errMessage == nullptr) {
CPLError(CE_Failure, CPLE_AppDefined, "no cached histogram available");
}
} else {
*values = (unsigned long long*) VSIMalloc(*buckets*sizeof(GUIntBig));
ret=GDALGetRasterHistogramEx(bnd,*min,*max,*buckets,*values,bIncludeOutOfRange,bApproxOK,nullptr,nullptr);
Expand Down
2 changes: 1 addition & 1 deletion godal.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ func (band Band) Histogram(opts ...HistogramOption) (Histogram, error) {
cgc := createCGOContext(nil, hopt.errorHandler)

C.godalRasterHistogram(cgc.cPointer(), band.handle(), (*C.double)(&hopt.min), (*C.double)(&hopt.max), (*C.int)(&hopt.buckets),
&values, C.int(hopt.includeOutside), C.int(hopt.approx))
&values, C.int(hopt.includeOutside), C.int(hopt.approx), C.int(hopt.force))
if err := cgc.close(); err != nil {
return Histogram{}, err
}
Expand Down
2 changes: 1 addition & 1 deletion godal.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ extern "C" {
void godalGetColorTable(GDALRasterBandH bnd, GDALPaletteInterp *interp, int *nEntries, short **entries);
void godalSetColorTable(cctx *ctx, GDALRasterBandH bnd, GDALPaletteInterp interp, int nEntries, short *entries);
void godalRasterHistogram(cctx *ctx, GDALRasterBandH bnd, double *min, double *max, int *buckets,
unsigned long long **values, int bIncludeOutOfRange, int bApproxOK);
unsigned long long **values, int bIncludeOutOfRange, int bApproxOK, int bForce);

VSILFILE *godalVSIOpen(cctx *ctx, const char *name);
void godalVSIUnlink(cctx *ctx, const char *name);
Expand Down
8 changes: 7 additions & 1 deletion godal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,9 +395,15 @@ func TestHistogram(t *testing.T) {
bnd := ds.Bands()[0]

_, err := bnd.Histogram()
assert.NoError(t, err)
assert.Error(t, err)
assert.Equal(t, "no cached histogram available", err.Error())

ehc := eh()
hist, err := bnd.Histogram(ErrLogger(ehc.ErrorHandler))
assert.Error(t, err)
assert.Equal(t, "no cached histogram available", err.Error())

hist, err = bnd.Histogram(Force())
assert.NoError(t, err)

ll := hist.Len()
Expand Down
26 changes: 23 additions & 3 deletions histogram.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@ func (h Histogram) Bucket(i int) Bucket {
}

type histogramOpts struct {
approx int
includeOutside int
approx int //bool
force int //bool
includeOutside int //bool
min, max float64
buckets int32
errorHandler ErrorHandler
Expand All @@ -55,6 +56,9 @@ type histogramOpts struct {
// - Approximate() to allow the algorithm to operate on a subset of the full resolution data
// - Intervals(count int, min,max float64) to compute a histogram with count buckets, spanning [min,max].
// Each bucket will be (max-min)/count wide. If not provided, the default histogram will be returned.
// - Force() to allow gdal to scan the full dataset to extract the histogram if no cached version
// is available. This option is not used if also using Intervals(). The default (i.e. without using
// Force()) is to return an error if a cached histogram is not available.
// - IncludeOutOfRange() to populate the first and last bucket with values under/over the specified min/max
// when used in conjuntion with Intervals()
// - ErrLogger
Expand Down Expand Up @@ -89,6 +93,20 @@ func Approximate() interface {
return approximateOkOption{}
}

type forceOption struct{}

func (aoo forceOption) setHistogramOpt(ho *histogramOpts) {
ho.force = 1
}

// Force allows the histogram algorithm to scan the dataset to collect statistics if a cached
// histogram is not available (false by default, may cause a long computation if set)
func Force() interface {
HistogramOption
} {
return forceOption{}
}

type intervalsOption struct {
min, max float64
buckets int32
Expand All @@ -101,7 +119,9 @@ func (io intervalsOption) setHistogramOpt(ho *histogramOpts) {
}

// Intervals computes a histogram with count buckets, spanning [min,max].
// Each bucket will be (max-min)/count wide. If not provided, the default histogram will be returned.
// Each bucket will be (max-min)/count wide.
// If provided, this option will force a dataset rescan which may be time consuming.
// If not provided, the default histogram will be returned
func Intervals(count int, min, max float64) interface {
HistogramOption
} {
Expand Down