Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

magnitude parameter #145

Open
Bontempogianpaolo1 opened this issue Sep 5, 2022 · 11 comments
Open

magnitude parameter #145

Bontempogianpaolo1 opened this issue Sep 5, 2022 · 11 comments

Comments

@Bontempogianpaolo1
Copy link

Hi,

thank you for your work. It is very amazing!
Is it possible to ask the actual magnitude level of the wsi instead of the relative level of the wsi? The reason is that I'm working on a dataset on a different scale magnitude and I have the feeling that using the patch level hyperparameter doesn't guarantee the same scale on every slide. Since I really need this feature I could even help somehow.

Thank you!

@fedshyvana
Copy link
Collaborator

hi, could you clarify what you mean by magnitude level? you can access standard metadata such as micron per pixel (mpp) and magnification from the openslide object if that's what you mean.

@Bontempogianpaolo1
Copy link
Author

does CLAM consider these parameters? Looking the code it seems it considers only the patch_level parameter. Am I wrong?

@fedshyvana
Copy link
Collaborator

correct - it does not. Our typical workflow just specifies the desired magnification level by setting the patch_level paramter. Without modifying the codebase, I believe if you have slides that are of different resolutions, and therefore require different patch_levels, you should be able to compute what the level should be for each slide in advance (e.g. by accessing the metadata), and then just passing that list of patch_levels to the script via the --process_list argument.

@fedshyvana
Copy link
Collaborator

I agree a better a way might be for the script to automatically parse out which patch_level to use, and give the user the option of just specifying the desired magnification level

@clemsgrs
Copy link

clemsgrs commented Nov 9, 2022

Hi @Bontempogianpaolo1, not sure if it's still relevant but I've implemented the functionality you were looking for as it happened I also needed it. Basically, I've created an additional method for the WholeSlideImage class that returns the level whose pixel spacing (in micron) is the closest to the target value passed by the user:

def get_best_level_for_spacing(self, target_spacing: float):
        # OpenSlide gives the resolution in centimeters so we convert this to microns
        x_res = float(self.wsi.properties['tiff.XResolution']) / 10000
        y_res = float(self.wsi.properties['tiff.YResolution']) / 10000
        x_spacing, y_spacing = 1 / x_res, 1 / y_res
        downsample_x, downsample_y = target_spacing / x_spacing, target_spacing / y_spacing
        # get_best_level_for_downsample just chooses the largest level with a downsample less than user's downsample
        # see https://github.com/openslide/openslide/issues/274
        # so I made my own version of get_best_level_for_downsample
        assert self.get_best_level_for_downsample_custom(downsample_x) == self.get_best_level_for_downsample_custom(downsample_y)
        level = self.get_best_level_for_downsample_custom(downsample_x)
        return level

This function leverages another method, get_best_level_for_downsample_custom, which is a quick workaround to fix the behaviour of openslide default get_best_level_for_downsample method:

def get_best_level_for_downsample_custom(self, downsample):
        return np.argmin([abs(x-downsample) for x in self.wsi.level_downsamples])

Then you should be good to go by simply adding a target_spacing argument to the self.process_contour method and add the following line at the beginning of that same method:

patch_level = self.get_best_level_for_spacing(target_spacing)

Remark: this works if

  • your slides all have the same pixel spacing at a given magnification
  • you want to patch at a magnification level smaller than or equal to the natural magnification level

For example, all my slides were acquired with an Aperio scanner, whose pixel spacing at 40x is 0.25 µm/pixel. Hence, by passing target_spacing = 0.50, I'm patching all slides at 20x.

Feel free to reach out if you have additional questions.

@GeorgeBatch
Copy link

There is another prerequisite. The resolution you want to get should be available at one of the levels.

Some slides (e.g. in TCGA) have downsample factors [1, 4, 16, 64] for levels [0, 1, 2, 3]. So the micron per pixel (mpp) values you can get with your code for your example are [0.25, 1, 4, 16] microns per pixel. So for 0.5 mpp and a target size of your tile 256 you would need to extract a tile of 512 pixels at 0.25 mpp and then resize it down to 256. So you still need to address this in the process list.

@iamownt
Copy link

iamownt commented Jan 6, 2025

There is another prerequisite. The resolution you want to get should be available at one of the levels.

Some slides (e.g. in TCGA) have downsample factors [1, 4, 16, 64] for levels [0, 1, 2, 3]. So the micron per pixel (mpp) values you can get with your code for your example are [0.25, 1, 4, 16] microns per pixel. So for 0.5 mpp and a target size of your tile 256 you would need to extract a tile of 512 pixels at 0.25 mpp and then resize it down to 256. So you still need to address this in the process list.

great, i also encouter this problem for TCGA dataset, as foundation models UNI/CONCH/Prov-Gigapath/TITAN all utilize 256 at 20X magnifcation, setting a patch level is impossible so that i have to resize~

@zaizaiwa
Copy link

I would like to ask, if I want to utilize 256 at 20X magnifcationon the TCGA dataset, how should I set the seg-level and patch-level?

@iamownt
Copy link

iamownt commented Jan 13, 2025

I would like to ask, if I want to utilize 256 at 20X magnifcationon the TCGA dataset, how should I set the seg-level and patch-level?

you can try this pull request, #287 (comment). It's not possible to set magnification directly in the CLAM repo, so that one possible way is to resize the image from 512 to 256 with 40X magnification following #145 (comment). Commonly, you should match the magnification with the patch level first

@clemsgrs
Copy link

In case you're interested, you can look into this repo: https://github.com/clemsgrs/hs2p

it's based on CLAM preprocessing, but come with some improvements, including being able to extract patches at a spacing not naturally present in the slide.

@GeorgeBatch
Copy link

GeorgeBatch commented Jan 14, 2025

@zaizaiwa @iamownt @clemsgrs, I think we should just focus on resolution in microns per pixel (mpp). If I remember correctly, TCGA has slides from all four combinations:

  • 20x, 0.5 mpp (standard)
  • 20x, 0.25 mpp
  • 40x, 0.5, mpp
  • 40x, 0.25 mpp (standard)

Because of the occasional non-standard scanning, getting a patch from a 20x magnification does not guarantee that you are working at the resolution UNI was trained on. But if you get a patch at 0.5 mpp, you don't need to worry about the magnification anymore.

I did not know about the hs2p repository @clemsgrs mentioned, so I added the support for UNI into TIAToolbox, where you can specify resolution in microns per pixel. Here is an example: https://github.com/TissueImageAnalytics/tiatoolbox/blob/develop/examples/11-import-foundation-models.ipynb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants