From 29198cb0de8977242d4505e145200e0c942c72ee Mon Sep 17 00:00:00 2001 From: David Manthey Date: Wed, 22 Sep 2021 15:09:44 -0400 Subject: [PATCH] Always have band number start at 1. This is in active use for the GDAL tile source; other tile sources should conform. --- CHANGELOG.md | 1 + girder/test_girder/test_tiles_rest.py | 4 ++-- large_image/tilesource/base.py | 19 +++++++++++-------- test/test_source_base.py | 14 +++++++++++--- test/test_source_pil.py | 4 ++-- 5 files changed, 27 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8581ea099..2ca2d3c9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Bug Fixes - getBandInformation could fail on high bands in some cases (#651) +- Band information should always be 1-indexed (#659) ## Version 1.8.0 diff --git a/girder/test_girder/test_tiles_rest.py b/girder/test_girder/test_tiles_rest.py index e809e48d2..6518d8032 100644 --- a/girder/test_girder/test_tiles_rest.py +++ b/girder/test_girder/test_tiles_rest.py @@ -1202,8 +1202,8 @@ def testTilesBandInformation(server, admin, fsAssetstore): server.request(path='/item/%s/tiles' % itemId, method='POST', user=admin) resp = server.request(path='/item/%s/tiles/bands' % itemId) assert len(resp.json) == 4 - assert resp.json[0]['interpretation'] == 'red' - assert 'mean' in resp.json[0] + assert resp.json['1']['interpretation'] == 'red' + assert 'mean' in resp.json['1'] @pytest.mark.usefixtures('unbindLargeImage') diff --git a/large_image/tilesource/base.py b/large_image/tilesource/base.py index a5c3724fe..18fcd41ce 100644 --- a/large_image/tilesource/base.py +++ b/large_image/tilesource/base.py @@ -1320,7 +1320,7 @@ def getOneBandInformation(self, band): """ Get band information for a single band. - :param band: a 0-based band. + :param band: a 1-based band. :returns: a dictionary of band information. See getBandInformation. """ return self.getBandInformation()[band] @@ -1331,8 +1331,9 @@ def getBandInformation(self, statistics=False, **kwargs): :param statistics: if True, compute statistics if they don't already exist. - :returns: a list of one dictionary per band. Each dictionary contains - known values such as interpretation, min, max, mean, stdev. + :returns: a dictionary of one dictionary per band. Each dictionary + contains known values such as interpretation, min, max, mean, + stdev. """ if not getattr(self, '_bandInfo', None): bandInterp = { @@ -1345,8 +1346,9 @@ def getBandInformation(self, statistics=False, **kwargs): tile = self.getSingleTile()['tile'] bands = tile.shape[2] if len(tile.shape) > 2 else 1 interp = bandInterp.get(bands, bandInterp[3]) - bandInfo = [{'interpretation': interp[idx] if idx < len(interp) else 'unknown'} - for idx in range(bands)] + bandInfo = { + idx + 1: {'interpretation': interp[idx] if idx < len(interp) + else 'unknown'} for idx in range(bands)} self._bandInfoNoStats = bandInfo return self._bandInfoNoStats analysisSize = 2048 @@ -1358,12 +1360,13 @@ def getBandInformation(self, statistics=False, **kwargs): **kwargs) bands = histogram['min'].shape[0] interp = bandInterp.get(bands, 3) - bandInfo = [{'interpretation': interp[idx] if idx < len(interp) else 'unknown'} - for idx in range(bands)] + bandInfo = { + idx + 1: {'interpretation': interp[idx] if idx < len(interp) + else 'unknown'} for idx in range(bands)} for key in {'min', 'max', 'mean', 'stdev'}: if key in histogram: for idx in range(bands): - bandInfo[idx][key] = histogram[key][idx] + bandInfo[idx + 1][key] = histogram[key][idx] self._bandInfo = bandInfo return self._bandInfo diff --git a/test/test_source_base.py b/test/test_source_base.py index b93093cd1..73e6aeff0 100644 --- a/test/test_source_base.py +++ b/test/test_source_base.py @@ -90,21 +90,29 @@ def testSourcesCanRead(source, filename): @pytest.mark.parametrize('filename', registry) @pytest.mark.parametrize('source', SourceAndFiles) -def testSourcesTiles(source, filename): +def testSourcesTilesAndMethods(source, filename): sourceInfo = SourceAndFiles[source] canRead = sourceInfo.get('any') or ( re.search(sourceInfo.get('read', r'^$'), filename) and not re.search(sourceInfo.get('noread', r'^$'), filename)) if not canRead: - return + pytest.skip('source does not work with this file') if re.search(sourceInfo.get('skipTiles', r'^$'), filename): - return + pytest.skip('source fails tile tests from this file') imagePath = datastore.fetch(filename) large_image.tilesource.loadTileSources() sourceClass = large_image.tilesource.AvailableTileSources[source] ts = sourceClass(imagePath) tileMetadata = ts.getMetadata() utilities.checkTilesZXY(ts, tileMetadata) + # All of these should succeed + assert ts.getInternalMetadata() is not None + assert ts.getOneBandInformation(1) is not None + assert len(ts.getBandInformation()) >= 1 + # Histograms are too slow to test in this way + # assert len(ts.histogram()['histogram']) >= 1 + # assert ts.histogram(onlyMinMax=True)['min'][0] is not None + # Test multiple frames if they exist if len(tileMetadata.get('frames', [])) > 1: tsf = sourceClass(imagePath, frame=len(tileMetadata['frames']) - 1) tileMetadata = tsf.getMetadata() diff --git a/test/test_source_pil.py b/test/test_source_pil.py index 0bde1b9e3..9bb706b3e 100644 --- a/test/test_source_pil.py +++ b/test/test_source_pil.py @@ -78,8 +78,8 @@ def testGetBandInformation(): source = large_image_source_pil.open(imagePath) bandInfo = source.getBandInformation(False) assert len(bandInfo) == 4 - assert bandInfo[0] == {'interpretation': 'red'} + assert bandInfo[1] == {'interpretation': 'red'} bandInfo = source.getBandInformation(True) assert len(bandInfo) == 4 - assert 'mean' in bandInfo[0] + assert 'mean' in bandInfo[1]