large_image icon indicating copy to clipboard operation
large_image copied to clipboard

[help] Get level shape

Open alevangel opened this issue 1 year ago • 6 comments

I'm having trouble obtaining the shape of the image level for each level. In OpenSlide, there is the parameter slide.level_dimensions[level], but I haven't found anything similar in this library. How can I accomplish that?

alevangel avatar Jun 12 '24 10:06 alevangel

I think you can do this with a combination of the getMetadata and convertRegionScale methods of tilesource.

https://github.com/girder/large_image/blob/2ac58341d5c59d163ed4ddfce0b424ac97950da3/large_image/tilesource/base.py#L1615

The lead developer is away on leave but can respond when he returns.

cooperlab avatar Jun 12 '24 14:06 cooperlab

@cooperlab using getMetadata, I can only obtain information about the Whole Slide Image at the highest resolution level. However, I would also like to retrieve the shapes of other resolution levels.

alevangel avatar Jun 12 '24 14:06 alevangel

I understand. Given the size and resolution of the native level, convertRegionScale can translate the "region" of the whole slide to other resolutions which would give you the corresponding size. large_image provides more flexibility in reading at off-level magnifications but it does complicate things a bit. I just wanted to provide a hint until @manthey can reply in case you need a quick solution.

cooperlab avatar Jun 12 '24 15:06 cooperlab

@cooperlab , very appreciated. Could you provide me with some example code? I can’t figure out how to implement it.

alevangel avatar Jun 12 '24 15:06 alevangel

I have attempted the following solution to address the problem at hand.

I am awaiting a response from @manthey to determine if there is a more robust solution available.

def _correct_level(self, level: int):
        max_level = self.slide.levels - 1
        # Large Image levels are in the opposite order of OpenSlide levels
        return max_level - level

def get_image_shape(self, level: int = 0):
level = self._correct_level(level)

# get magnification for level
mag = self.slide.getMagnificationForLevel(level)
metadata = self.slide.metadata

left, top, right, bottom = self.slide._getRegionBounds(
    metadata, desiredMagnification=mag)
regionWidth = right - left
regionHeight = bottom - top

if mag.get('scale') in (1.0, None):
    maxWidth, maxHeight = regionWidth, regionHeight
else:
    maxWidth = regionWidth / cast(float, mag['scale'])
    maxHeight = regionHeight / cast(float, mag['scale'])

outWidth, outHeight, calcScale = large_image.tilesource.utilities._calculateWidthHeight(
    maxWidth, maxHeight, regionWidth, regionHeight)

return outHeight, outWidth

I adapted the code provided here:

https://github.com/girder/large_image/blob/2ac58341d5c59d163ed4ddfce0b424ac97950da3/large_image/tilesource/tileiterator.py#L211C1-L227C60

alevangel avatar Jun 12 '24 16:06 alevangel

@alevangel you can also use the result of getMetadata to define a region that is the entire slide full magnification, and then convert this to other magnifications using convertRegionScale. You would set sourceRegion['units']='base_pixels' and then use getMagnificationForLevel to determine the targetScale argument value.

cooperlab avatar Jun 12 '24 19:06 cooperlab

Closing this. Please reopen or start a discussion if appropriate.

manthey avatar Feb 13 '25 15:02 manthey