Skip to content

Commit 3ff91f4

Browse files
committed
GDALDataset::[Get|Compute]InterBandCovarianceMatrix(): allow to pass subset of bands
1 parent 0c14d8b commit 3ff91f4

File tree

9 files changed

+488
-566
lines changed

9 files changed

+488
-566
lines changed

autotest/gcore/gdal_stats.py

Lines changed: 62 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,10 +1281,14 @@ def my_progress(pct, msg, user_data):
12811281
)
12821282
) == pytest.approx(list(chain.from_iterable(expected_cov_matrix)))
12831283

1284-
assert tab_pct[0] == 1.0
1284+
assert tab_pct[0] == 1.0
12851285

1286-
with gdal.Open(tmp_vsimem / "test.tif") as ds:
1287-
assert ds.GetInterBandCovarianceMatrix() is None
1286+
res = ds.GetInterBandCovarianceMatrix(
1287+
band_list=[2], force=True, write_into_metadata=False
1288+
)
1289+
assert res[0][0] == pytest.approx(expected_cov_matrix[1][1])
1290+
1291+
assert gdal.VSIStatL(tmp_vsimem / "test.tif.aux.xml") is None
12881292

12891293

12901294
###############################################################################
@@ -1293,13 +1297,35 @@ def my_progress(pct, msg, user_data):
12931297
def test_stats_GetInterBandCovarianceMatrix_edge_cases():
12941298

12951299
ds = gdal.GetDriverByName("MEM").Create("", 0, 0, 0)
1296-
with pytest.raises(Exception, match="Zero band dataset"):
1300+
with pytest.raises(Exception, match="Empty list"):
12971301
ds.GetInterBandCovarianceMatrix(force=True)
12981302

12991303

13001304
###############################################################################
13011305

13021306

1307+
def test_stats_GetInterBandCovarianceMatrix_errors_on_band_list():
1308+
1309+
ds = gdal.GetDriverByName("MEM").Create("", 1, 1, 2)
1310+
with pytest.raises(Exception, match=" invalid value"):
1311+
ds.GetInterBandCovarianceMatrix(band_list=[0])
1312+
with pytest.raises(Exception, match="invalid value"):
1313+
ds.GetInterBandCovarianceMatrix(band_list=[3])
1314+
with pytest.raises(Exception, match="nBandCount > nBands"):
1315+
ds.GetInterBandCovarianceMatrix(band_list=[1, 1, 1])
1316+
with pytest.raises(Exception, match="cannot write STATISTICS_COVARIANCES metadata"):
1317+
ds.GetInterBandCovarianceMatrix(
1318+
band_list=[1], force=True, write_into_metadata=True
1319+
)
1320+
with pytest.raises(Exception, match="cannot write STATISTICS_COVARIANCES metadata"):
1321+
ds.GetInterBandCovarianceMatrix(
1322+
band_list=[2, 1], force=True, write_into_metadata=True
1323+
)
1324+
1325+
1326+
###############################################################################
1327+
1328+
13031329
def test_stats_ComputeInterBandCovarianceMatrix(tmp_vsimem):
13041330

13051331
gdal.FileFromMemBuffer(
@@ -1362,10 +1388,14 @@ def my_progress(pct, msg, user_data):
13621388
)
13631389
) == pytest.approx(list(chain.from_iterable(expected_cov_matrix)))
13641390

1365-
assert tab_pct[0] == 1.0
1391+
assert tab_pct[0] == 1.0
13661392

1367-
with gdal.Open(tmp_vsimem / "test.tif") as ds:
1368-
assert ds.GetInterBandCovarianceMatrix() is None
1393+
res = ds.ComputeInterBandCovarianceMatrix(
1394+
band_list=[2], write_into_metadata=False
1395+
)
1396+
assert res[0][0] == pytest.approx(expected_cov_matrix[1][1])
1397+
1398+
assert gdal.VSIStatL(tmp_vsimem / "test.tif.aux.xml") is None
13691399

13701400

13711401
###############################################################################
@@ -1378,9 +1408,9 @@ def test_stats_ComputeInterBandCovarianceMatrix_overviews(tmp_vsimem):
13781408
ds.Close()
13791409

13801410
expected_cov_matrix = [
1381-
[2241.7474621754936, 2898.723016592399, 1010.1568325910154],
1382-
[2898.723016592399, 3900.259907723227, 1248.630954306772],
1383-
[1010.1568325910154, 1248.630954306772, 601.9344108086958],
1411+
[2241.747462182087, 2898.723016609931, 1010.1568325853924],
1412+
[2898.723016609931, 3900.2599077296286, 1248.6309543003213],
1413+
[1010.1568325853924, 1248.6309543003213, 601.9344108053141],
13841414
]
13851415

13861416
with gdal.Open(tmp_vsimem / "test.tif") as ds:
@@ -1396,13 +1426,31 @@ def test_stats_ComputeInterBandCovarianceMatrix_overviews(tmp_vsimem):
13961426
def test_stats_ComputeInterBandCovarianceMatrix_edge_cases():
13971427

13981428
ds = gdal.GetDriverByName("MEM").Create("", 0, 0, 0)
1399-
with pytest.raises(Exception, match="Zero band dataset"):
1429+
with pytest.raises(Exception, match="Empty list"):
14001430
ds.ComputeInterBandCovarianceMatrix()
14011431

14021432

14031433
###############################################################################
14041434

14051435

1436+
def test_stats_ComputeInterBandCovarianceMatrix_errors_on_band_list():
1437+
1438+
ds = gdal.GetDriverByName("MEM").Create("", 1, 1, 2)
1439+
with pytest.raises(Exception, match=" invalid value"):
1440+
ds.ComputeInterBandCovarianceMatrix(band_list=[0])
1441+
with pytest.raises(Exception, match="invalid value"):
1442+
ds.ComputeInterBandCovarianceMatrix(band_list=[3])
1443+
with pytest.raises(Exception, match="nBandCount > nBands"):
1444+
ds.ComputeInterBandCovarianceMatrix(band_list=[1, 1, 1])
1445+
with pytest.raises(Exception, match="cannot write STATISTICS_COVARIANCES metadata"):
1446+
ds.ComputeInterBandCovarianceMatrix(band_list=[1], write_into_metadata=True)
1447+
with pytest.raises(Exception, match="cannot write STATISTICS_COVARIANCES metadata"):
1448+
ds.ComputeInterBandCovarianceMatrix(band_list=[2, 1], write_into_metadata=True)
1449+
1450+
1451+
###############################################################################
1452+
1453+
14061454
def test_stats_ComputeInterBandCovarianceMatrix_nodata():
14071455

14081456
ds = gdal.GetDriverByName("MEM").Create("", 4, 1, 2)
@@ -1490,34 +1538,14 @@ def test_stats_ComputeInterBandCovarianceMatrix_mask_band():
14901538
###############################################################################
14911539

14921540

1493-
def test_stats_ComputeInterBandCovarianceMatrix_mask_band_per_dataset():
1494-
1495-
ds = gdal.GetDriverByName("MEM").Create("", 4, 1, 2)
1496-
ds.CreateMaskBand(gdal.GMF_PER_DATASET)
1497-
ds.GetRasterBand(1).WriteRaster(0, 0, 4, 1, b"\x01\x02\x03\xFF")
1498-
ds.GetRasterBand(2).WriteRaster(0, 0, 4, 1, b"\x02\x01\xFE\x03")
1499-
ds.GetRasterBand(1).GetMaskBand().WriteRaster(0, 0, 4, 1, b"\xFF\xFF\x00\x00")
1500-
1501-
expected_cov_matrix = [[0.5, -0.5], [-0.5, 0.5]]
1502-
1503-
cov_matrix = ds.ComputeInterBandCovarianceMatrix()
1504-
assert list(chain.from_iterable(cov_matrix)) == pytest.approx(
1505-
list(chain.from_iterable(expected_cov_matrix))
1506-
)
1507-
1508-
1509-
###############################################################################
1510-
1511-
1512-
@pytest.mark.slow()
1513-
def test_stats_ComputeInterBandCovarianceMatrix_huge_mem_alloc():
1541+
def test_stats_ComputeInterBandCovarianceMatrix_interrupt():
15141542

1515-
ds = gdal.GetDriverByName("MEM").Create("", 1, 1, 50000)
1543+
ds = gdal.GetDriverByName("MEM").Create("", 1, 1, 1000)
15161544

15171545
def my_progress(pct, msg, user_data):
15181546
return pct < 1e-2
15191547

1520-
with pytest.raises(Exception):
1548+
with pytest.raises(Exception, match="User terminated"):
15211549
ds.ComputeInterBandCovarianceMatrix(
15221550
write_into_metadata=False, callback=my_progress
15231551
)

gcore/gdal.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,14 +1360,16 @@ CPLErr CPL_DLL GDALDatasetGeolocationToPixelLine(
13601360
double *pdfPixel, double *pdfLine, CSLConstList papszTransformerOptions);
13611361

13621362
CPLErr CPL_DLL GDALDatasetGetInterBandCovarianceMatrix(
1363-
GDALDatasetH hDS, double *padfCovMatrix, size_t nSize, bool bApproxOK,
1364-
bool bForce, bool bWriteIntoMetadata, int nDeltaDegreeOfFreedom,
1363+
GDALDatasetH hDS, double *padfCovMatrix, size_t nSize, int nBandCount,
1364+
const int *panBandList, bool bApproxOK, bool bForce,
1365+
bool bWriteIntoMetadata, int nDeltaDegreeOfFreedom,
13651366
GDALProgressFunc pfnProgress, void *pProgressData);
13661367

13671368
CPLErr CPL_DLL GDALDatasetComputeInterBandCovarianceMatrix(
1368-
GDALDatasetH hDS, double *padfCovMatrix, size_t nSize, bool bApproxOK,
1369-
bool bWriteIntoMetadata, int nDeltaDegreeOfFreedom,
1370-
GDALProgressFunc pfnProgress, void *pProgressData);
1369+
GDALDatasetH hDS, double *padfCovMatrix, size_t nSize, int nBandCount,
1370+
const int *panBandList, bool bApproxOK, bool bWriteIntoMetadata,
1371+
int nDeltaDegreeOfFreedom, GDALProgressFunc pfnProgress,
1372+
void *pProgressData);
13711373

13721374
int CPL_DLL CPL_STDCALL GDALGetGCPCount(GDALDatasetH);
13731375
const char CPL_DLL *CPL_STDCALL GDALGetGCPProjection(GDALDatasetH);

gcore/gdal_dataset.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -511,25 +511,27 @@ class CPL_DLL GDALDataset : public GDALMajorObject
511511
GDALProgressFunc pfnProgress,
512512
void *pProgressData, CSLConstList papszOptions);
513513

514-
CPLErr GetInterBandCovarianceMatrix(double *padfCovMatrix, size_t nSize,
515-
bool bApproxOK = false,
516-
bool bForce = false,
517-
bool bWriteIntoMetadata = true,
518-
int nDeltaDegreeOfFreedom = 1,
519-
GDALProgressFunc pfnProgress = nullptr,
520-
void *pProgressData = nullptr);
514+
CPLErr GetInterBandCovarianceMatrix(
515+
double *padfCovMatrix, size_t nSize, int nBandCount = 0,
516+
const int *panBandList = nullptr, bool bApproxOK = false,
517+
bool bForce = false, bool bWriteIntoMetadata = true,
518+
int nDeltaDegreeOfFreedom = 1, GDALProgressFunc pfnProgress = nullptr,
519+
void *pProgressData = nullptr);
521520

522521
std::vector<double> GetInterBandCovarianceMatrix(
522+
int nBandCount = 0, const int *panBandList = nullptr,
523523
bool bApproxOK = false, bool bForce = false,
524524
bool bWriteIntoMetadata = true, int nDeltaDegreeOfFreedom = 1,
525525
GDALProgressFunc pfnProgress = nullptr, void *pProgressData = nullptr);
526526

527527
CPLErr ComputeInterBandCovarianceMatrix(
528-
double *padfCovMatrix, size_t nSize, bool bApproxOK = false,
528+
double *padfCovMatrix, size_t nSize, int nBandCount = 0,
529+
const int *panBandList = nullptr, bool bApproxOK = false,
529530
bool bWriteIntoMetadata = true, int nDeltaDegreeOfFreedom = 1,
530531
GDALProgressFunc pfnProgress = nullptr, void *pProgressData = nullptr);
531532

532533
std::vector<double> ComputeInterBandCovarianceMatrix(
534+
int nBandCount = 0, const int *panBandList = nullptr,
533535
bool bApproxOK = false, bool bWriteIntoMetadata = true,
534536
int nDeltaDegreeOfFreedom = 1, GDALProgressFunc pfnProgress = nullptr,
535537
void *pProgressData = nullptr);

gcore/gdal_rasterband.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -502,14 +502,6 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
502502
double *pdfMax, double *pdfMean,
503503
double *pdfStdDev, GDALProgressFunc,
504504
void *pProgressData);
505-
506-
double ComputeInterBandCovariance(
507-
GDALRasterBand *poOtherBand, bool bApproxOK = false,
508-
int nDeltaDegreeOfFreedom = 1, const double *pdfThisBandMean = nullptr,
509-
const double *pdfOtherBandMean = nullptr,
510-
std::vector<double> *padfTempVector = nullptr,
511-
GDALProgressFunc = nullptr, void *pProgressData = nullptr);
512-
513505
virtual CPLErr SetStatistics(double dfMin, double dfMax, double dfMean,
514506
double dfStdDev);
515507
virtual CPLErr ComputeRasterMinMax(int bApproxOK, double *adfMinMax);

0 commit comments

Comments
 (0)