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

WSIReader support for reading by mpp or magnification #4980

Open
drbeh opened this issue Aug 23, 2022 · 10 comments · May be fixed by #7574
Open

WSIReader support for reading by mpp or magnification #4980

drbeh opened this issue Aug 23, 2022 · 10 comments · May be fixed by #7574
Assignees
Labels
Pathology/Microscopy Digital Pathology and Microscopy related

Comments

@drbeh
Copy link
Member

drbeh commented Aug 23, 2022

In MONAI Pathology WG, we have discussed about the need for being able to read whole slide images at specific resolution (mpp or magnification) in addition to reading at a specific level. The feature request has been made by @cooperlab in cucim repo rapidsai/cucim#389.

I have discussed with cuCIM team about this topic and the conclusion was that it may be more useful to implement this functionality in MONA rather than in cucim for few reasons:

  • this feature will be automatically supported for all the backends (cuCIM, OpenSlide, TiffFile, etc)
  • the changes in magnification can be tracked in MONAI and be used to invert the process

To achieve this, the following functionalities need to be added to MOANI WSIReader:

  • to find the next higher level to the requested mpp or magnification
  • load the requested image that level with the appropriate pre-resized size
  • resample/resize the image to the target mpp/magnification
@drbeh drbeh added the Pathology/Microscopy Digital Pathology and Microscopy related label Aug 23, 2022
@drbeh drbeh changed the title WSIReader support for read by magnification WSIReader support for reading by magnification Aug 23, 2022
@drbeh
Copy link
Member Author

drbeh commented Aug 23, 2022

@cooperlab what do you think?

@cooperlab
Copy link

cooperlab commented Aug 23, 2022

@drbeh LGTM. The guiding principles here are that developers shouldn't have to do a lot of calculations to determine what they have or what's been done to it, and to make clear what definitions like location correspond to.

@drbeh drbeh self-assigned this Feb 23, 2023
@drbeh drbeh changed the title WSIReader support for reading by magnification WSIReader support for reading by mpp or magnification Sep 26, 2023
@NikolasSchmitz
Copy link

Hi @drbeh , as discussed in the MONAI meeting last Tuesday, I will have a look at this issue. In our group we solved a similar problem and this might work here as well!

@drbeh drbeh assigned drbeh and NikolasSchmitz and unassigned drbeh Oct 10, 2023
@NikolasSchmitz
Copy link

Hi @drbeh, sorry for the delay, but I am almost done with a first implementation. However, there are a few detailed questions I have to make sure that the function gives the desired output. Should I post them here, or should I ask them in the next monai core meeting?

@drbeh
Copy link
Member Author

drbeh commented Feb 5, 2024

Hi @NikolasSchmitz, that is fantastic! It's best if you ask here to make sure that anyone with an answer can help and then followup in our next meeting. Thanks

@NikolasSchmitz
Copy link

Okay, sure! Assuming the simple and straightforward solution to this matter, we would take the image at the next lower wsi level and then downscale it to a resolution that fits the user-provided mpp value.
In some cases, e.g., if the user-provided mpp is just slightly below the mpp of a certain wsi level, taking the next lower level might lead to unnecessarily compute-intensive downscaling operations. Let's say our wsi has an mpp of 1 at wsi level 1, and an mpp of 0.5 at wsi level 0. The user wants an image of the wsi that has 0.95 mpp. We would then have three options:

  1. Take the image at wsi level 0 and downscale.
  2. Take the image at wsi level 1 and upscale.
  3. Take the image at wsi level 1 without modification (e.g., with the use of tolerance criteria which the user can overwrite).

Personally, I would prefer 3. with a default value for tolerances atol and rtol. If one of the wsi levels is within the user's mpp +/- tolerance, then we can safely select the corresponding wsi level. Otherwise, we can scale down from the next larger representation of the wsi.

I attached three images showing three cases, where case 1 shows the simple and straightforward solution, and cases 2 and 3 show the above described issue without and with a tolerance range. I thought it might help to visualize the problem.

My questions are now:

  1. Is the above a fitting description of what should be implemented? What else is missing? I am pretty sure there are more edge cases we need to take care of, e.g., restricting the user-mpp to be => mpp at wsi level 0 etc.
  2. Should we prevent any form of upscaling, or should we let the user decide?

Image
Image
Image

@cooperlab
Copy link

@NikolasSchmitz my suggestion re upscaling is that users should have to opt-in to enable this. It's uncommon but I really like the option to save compute if the next highest magnification is very large.

@drbeh
Copy link
Member Author

drbeh commented Feb 13, 2024

@NikolasSchmitz Just to summarize what we discussed about your questions:

  • Follow the existing logic for checking if the specific magnification power or MPP exists in the WSI considering the absolute and relative tolerances (similar to your Case 3)
    def _find_closest_level(
    self, name: str, value: tuple, value_at_levels: Sequence[tuple], atol: float, rtol: float
    ) -> int:
    """Find the level corresponding to the value of the quantity in the list of values at each level.
    Args:
    name: the name of the requested quantity
    value: the value of requested quantity
    value_at_levels: list of value of the quantity at each level
    atol: the tolerance for the value
    rtol: relative tolerance for the value
    """
    if value in value_at_levels:
    return value_at_levels.index(value)
    closest_value = min(value_at_levels, key=lambda a_value: sum([abs(x - y) for x, y in zip(a_value, value)]))
    for i in range(len(value)):
    if abs(closest_value[i] - value[i]) > atol + rtol * abs(value[i]):
    raise ValueError(
    f"The requested {name} < {value} > does not exist in this whole slide image "
    f"(with {name}_rtol={rtol} and {name}_atol={atol}). "
    f"Here is the list of available {name}: {value_at_levels}. "
    f"The closest matching available {name} is {closest_value}."
    f"Please consider changing the tolerances or use another {name}."
    )
    return value_at_levels.index(closest_value)
  • Always downsample unless explicitly asked by the user.
  • The only situation that makes sense for upsampling by default is when the requested magnification is larger than the highest available magnification (equivalently request mpp is smaller than lowest available mpp). In this case, a warning should be given to the user too if it is not explicitly ask for.

Please do not hesitate to reach out if you have any other questions and thanks for contributing to MONAI.

@NikolasSchmitz
Copy link

Thanks for the helpful feedback, everyone! I will create the draft pull request in the next days and implement what we discussed.

@NikolasSchmitz
Copy link

NikolasSchmitz commented Mar 24, 2024

This feature was added in #7574

@NikolasSchmitz NikolasSchmitz linked a pull request Mar 25, 2024 that will close this issue
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Pathology/Microscopy Digital Pathology and Microscopy related
Projects
Status: 🌋 In Progress
Development

Successfully merging a pull request may close this issue.

3 participants