Skip to content

Commit

Permalink
Merge pull request #668 from girder/warn-ometiff
Browse files Browse the repository at this point in the history
Improve warnings on inefficient tiff files.
  • Loading branch information
manthey authored Oct 20, 2021
2 parents c7c2c59 + 0a77d24 commit ee40f7b
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 6 deletions.
11 changes: 11 additions & 0 deletions sources/ometiff/large_image_source_ometiff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ class OMETiffFileTileSource(TiffFileTileSource, metaclass=LruCacheMetaclass):
'ome': SourcePriority.PREFERRED,
}

# The expect number of pixels that would need to be read to read the worst-
# case tile.
_maxUntiledChunk = 512 * 1024 * 1024

def __init__(self, path, **kwargs):
"""
Initialize the tile class. See the base class for other available
Expand Down Expand Up @@ -123,6 +127,12 @@ def __init__(self, path, **kwargs):
TiledTiffDirectory(largeImagePath, 0, mustBeTiled=None)
if entry else None
for entry in self._omeLevels]
self._checkForInefficientDirectories(warn=False)
_maxChunk = min(base.imageWidth, base.tileWidth * self._skippedLevels ** 2) * \
min(base.imageHeight, base.tileHeight * self._skippedLevels ** 2)
if _maxChunk > self._maxUntiledChunk:
raise TileSourceError(
'Untiled image is too large to access with the OME Tiff source')
self.tileWidth = base.tileWidth
self.tileHeight = base.tileHeight
self.levels = len(self._tiffDirectories)
Expand All @@ -133,6 +143,7 @@ def __init__(self, path, **kwargs):
# images as associated images. This would require enumerating tiff
# directories not mentioned by the ome list.
self._associatedImages = {}
self._checkForInefficientDirectories()

def _checkForOMEZLoop(self, largeImagePath):
"""
Expand Down
22 changes: 16 additions & 6 deletions sources/tiff/large_image_source_tiff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ def __init__(self, path, **kwargs):
self.levels = len(self._tiffDirectories)
self.sizeX = highest.imageWidth
self.sizeY = highest.imageHeight
self._checkForInefficientDirectories()

def _scanDirectories(self):
largeImagePath = self._largeImagePath
Expand Down Expand Up @@ -314,16 +315,25 @@ def _initWithTiffTools(self): # noqa
if frames[0]['dirs'][idx] is not None else None
for idx in range(self.levels - 1)]
self._tiffDirectories.append(dir0)
self._checkForInefficientDirectories()
return True

def _checkForInefficientDirectories(self, warn=True):
"""
Raise a warning for inefficient files.
:param warn: if True and inefficient, emit a warning.
"""
missing = [v is None for v in self._tiffDirectories]
maxMissing = max(0 if not v else missing.index(False, idx) - idx
for idx, v in enumerate(missing))
self._skippedLevels = maxMissing
if maxMissing >= self._maxSkippedLevels:
config.getConfig('logger').warning(
'Tiff image is missing many lower resolution levels (%d). '
'It will be inefficient to read lower resolution tiles.', maxMissing)
if warn:
config.getConfig('logger').warning(
'Tiff image is missing many lower resolution levels (%d). '
'It will be inefficient to read lower resolution tiles.', maxMissing)
self._inefficientWarning = True
return True

def _reorient_numpy_image(self, image, orientation):
"""
Expand Down Expand Up @@ -631,8 +641,8 @@ def getTileFromEmptyDirectory(self, x, y, z, **kwargs):
while z - basez > self._maxSkippedLevels:
z -= self._maxSkippedLevels
scale = int(scale / 2 ** self._maxSkippedLevels)
tile = PIL.Image.new(
'RGBA', (self.tileWidth * scale, self.tileHeight * scale))
tile = PIL.Image.new('RGBA', (
min(self.sizeX, self.tileWidth * scale), min(self.sizeY, self.tileHeight * scale)))
maxX = 2.0 ** (z + 1 - self.levels) * self.sizeX / self.tileWidth
maxY = 2.0 ** (z + 1 - self.levels) * self.sizeY / self.tileHeight
for newX in range(scale):
Expand Down

0 comments on commit ee40f7b

Please sign in to comment.