Skip to content

Commit

Permalink
Handle bounds on openslide sources to handle sparse sources
Browse files Browse the repository at this point in the history
Resolves #1470
  • Loading branch information
manthey authored and gabrielle6249 committed Jul 10, 2024
1 parent fc93571 commit 34586a4
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 1 deletion.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Change Log

## 1.28.3
## 1.29.0

### Features
- Add redis as cache backend option ([#1469](../../pull/1469))
Expand All @@ -10,6 +10,7 @@
- Reject the promise from a canceled annotation ([#1535](../../pull/1535))
- Disallow certain names from being read by any but specific sources ([#1537](../../pull/1537))
- Add the ability to specify the dtype of a multi-source file ([#1542](../../pull/1542))
- Handle bounds on openslide sources to handle sparse sources ([#1543](../../pull/1543))

### Changes
- Log more when saving annotations ([#1525](../../pull/1525))
Expand Down
27 changes: 27 additions & 0 deletions sources/openslide/large_image_source_openslide/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,30 @@ def __init__(self, path, **kwargs): # noqa
'svslevel': bestlevel,
'scale': scale,
})
self._bounds = None
try:
bounds = {
'x': int(self._openslide.properties[openslide.PROPERTY_NAME_BOUNDS_X]),
'y': int(self._openslide.properties[openslide.PROPERTY_NAME_BOUNDS_Y]),
'width': int(self._openslide.properties[openslide.PROPERTY_NAME_BOUNDS_WIDTH]),
'height': int(self._openslide.properties[openslide.PROPERTY_NAME_BOUNDS_HEIGHT]),
}
if (
bounds['x'] >= 0 and bounds['width'] > 0 and
bounds['x'] + bounds['width'] <= self.sizeX and
bounds['y'] >= 0 and bounds['height'] > 0 and
bounds['y'] + bounds['height'] <= self.sizeY and
(bounds['width'] < self.sizeX or bounds['height'] < self.sizeY)
):
self._bounds = bounds
self.sizeX, self.sizeY = bounds['width'], bounds['height']
prevlevels = self.levels
self.levels = int(math.ceil(max(
math.log(float(self.sizeX) / self.tileWidth),
math.log(float(self.sizeY) / self.tileHeight)) / math.log(2))) + 1
self._svslevels = self._svslevels[prevlevels - self.levels:]
except Exception:
pass
self._populatedLevels = len({l['svslevel'] for l in self._svslevels})

def _getTileSize(self):
Expand Down Expand Up @@ -292,6 +316,9 @@ def getTile(self, x, y, z, pilImageAllowed=False, numpyAllowed=False, **kwargs):
scale = 2 ** (self.levels - 1 - z)
offsetx = x * self.tileWidth * scale
offsety = y * self.tileHeight * scale
if self._bounds is not None:
offsetx += self._bounds['x'] // svslevel['scale']
offsety += self._bounds['y'] // svslevel['scale']
# We ask to read an area that will cover the tile at the z level. The
# scale we computed in the __init__ process for this svs level tells
# how much larger a region we need to read.
Expand Down

0 comments on commit 34586a4

Please sign in to comment.