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

Feature added: Get WSI at mpp #7574

Open
wants to merge 15 commits into
base: dev
Choose a base branch
from

Conversation

NikolasSchmitz
Copy link

@NikolasSchmitz NikolasSchmitz commented Mar 25, 2024

Fixes: #4980

Description

In this pull request, the feature to retrieve a whole slide image at a given mpp (microns per pixel) resolution was implemented for every WSIReader class in the function get_wsi_at_mpp.

While the implementations in the OpenslideWSIReader and CuCIMWSIReader classes were tested thoroughly, I could not find a suitable TIFF file for testing with the TiffFileWSIReader class.

For resizing, I have used PIL.Image.resize for Openslide and TiffFile, and cucim.sklearn.transform.resize for CuCIM. Originally, I used cv2.resize, but since the package isn't listed in requirements-dev.txt, I explored alternative solutions."

Types of changes

  • Non-breaking change (fix or new feature that would not break existing functionality).
  • Breaking change (fix or new feature that would cause existing functionality to change).
  • New tests added to cover the changes.
  • Integration tests passed locally by running ./runtests.sh -f -u --net --coverage.
  • Quick tests passed locally by running ./runtests.sh --quick --unittests --disttests.
  • In-line docstrings updated.
  • Documentation updated, tested make html command in the docs/ folder.

Please let me know what you think and how I can improve this feature.

Best
Niko

(Last PR was closed, because I changed the branch name to include the ticket id)

cxlcl and others added 6 commits March 27, 2024 01:47
…roject-MONAI#7308)

### Description

Based on the discussion topic
[here](Project-MONAI#7161 (comment)),
we implemented the Conjugate-Gradient algorithm for linear operator
inversion, and Stein's Unbiased Risk Estimator (SURE) [1] loss for
ground-truth-date free diffusion process guidance that is proposed in
[2] and illustrated in the algorithm below:

<img width="650" alt="Screenshot 2023-12-10 at 10 19 25 PM"
src="https://github.com/Project-MONAI/MONAI/assets/8581162/97069466-cbaf-44e0-b7a7-ae9deb8fd7f2">

The Conjugate-Gradient (CG) algorithm is used to solve for the inversion
of the linear operator in Line-4 in the algorithm above, where the
linear operator is too large to store explicitly as a matrix (such as
FFT/IFFT of an image) and invert directly. Instead, we can solve for the
linear inversion iteratively as in CG.

The SURE loss is applied for Line-6 above. This is a differentiable loss
function that can be used to train/giude an operator (e.g. neural
network), where the pseudo ground truth is available but the reference
ground truth is not. For example, in the MRI reconstruction, the pseudo
ground truth is the zero-filled reconstruction and the reference ground
truth is the fully sampled reconstruction. The reference ground truth is
not available due to the lack of fully sampled.

**Reference**
[1] Stein, C.M.: Estimation of the mean of a multivariate normal
distribution. Annals of Statistics 1981 [[paper
link](https://projecteuclid.org/journals/annals-of-statistics/volume-9/issue-6/Estimation-of-the-Mean-of-a-Multivariate-Normal-Distribution/10.1214/aos/1176345632.full)]
[2] B. Ozturkler et al. SMRD: SURE-based Robust MRI Reconstruction with
Diffusion Models. MICCAI 2023
[[paper link](https://arxiv.org/pdf/2310.01799.pdf)]

### Types of changes
<!--- Put an `x` in all the boxes that apply, and remove the not
applicable items -->
- [x] Non-breaking change (fix or new feature that would not break
existing functionality).
- [ ] Breaking change (fix or new feature that would cause existing
functionality to change).
- [x] New tests added to cover the changes.
- [x] Integration tests passed locally by running `./runtests.sh -f -u
--net --coverage`.
- [x] Quick tests passed locally by running `./runtests.sh --quick
--unittests --disttests`.
- [x] In-line docstrings updated.
- [x] Documentation updated, tested `make html` command in the `docs/`
folder.

---------

Signed-off-by: chaoliu <[email protected]>
Signed-off-by: cxlcl <[email protected]>
Signed-off-by: chaoliu <[email protected]>
Signed-off-by: YunLiu <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: YunLiu <[email protected]>
Co-authored-by: Eric Kerfoot <[email protected]>
Signed-off-by: Nikolas Schmitz <[email protected]>
Signed-off-by: Nikolas Schmitz <[email protected]>
Signed-off-by: Nikolas Schmitz <[email protected]>
Signed-off-by: monai-bot <[email protected]>

Signed-off-by: monai-bot <[email protected]>
Signed-off-by: Nikolas Schmitz <[email protected]>
Signed-off-by: Nikolas Schmitz <[email protected]>
NikolasSchmitz and others added 3 commits March 27, 2024 02:04
Signed-off-by: Nikolas Schmitz <[email protected]>
…ject-MONAI#7569)

Fixes Project-MONAI#7451

### Description
Reduces the length of error messages and error messages being propagated
twice. This helps debug better when long `ConfigComponent`s are being
instantiated. Refer to issue Project-MONAI#7451 for more details

### Types of changes
<!--- Put an `x` in all the boxes that apply, and remove the not
applicable items -->
- [x] Non-breaking change (fix or new feature that would not break
existing functionality).
- [ ] Breaking change (fix or new feature that would cause existing
functionality to change).
- [ ] New tests added to cover the changes.
- [ ] Integration tests passed locally by running `./runtests.sh -f -u
--net --coverage`.
- [x] Quick tests passed locally by running `./runtests.sh --quick
--unittests --disttests`.
- [ ] In-line docstrings updated.
- [ ] Documentation updated, tested `make html` command in the `docs/`
folder.

Signed-off-by: Suraj Pai <[email protected]>
Co-authored-by: Eric Kerfoot <[email protected]>
Fixes Project-MONAI#2872 

### Description

Implementation of mixup, cutmix and cutout as described in the original
papers.
Current implementation support both, the dictionary-based batches and
tuples of tensors.

### Types of changes
<!--- Put an `x` in all the boxes that apply, and remove the not
applicable items -->
- [x] Non-breaking change (fix or new feature that would not break
existing functionality).
- [ ] Breaking change (fix or new feature that would cause existing
functionality to change).
- [x] New tests added to cover the changes.
- [ ] Integration tests passed locally by running `./runtests.sh -f -u
--net --coverage`.
- [x] Quick tests passed locally by running `./runtests.sh --quick
--unittests --disttests`.
- [x] In-line docstrings updated.
- [x] Documentation updated, tested `make html` command in the `docs/`
folder.

---------

Signed-off-by: Juan Pablo de la Cruz Gutiérrez <[email protected]>
Signed-off-by: monai-bot <[email protected]>
Signed-off-by: elitap <[email protected]>
Signed-off-by: Felix Schnabel <[email protected]>
Signed-off-by: YanxuanLiu <[email protected]>
Signed-off-by: ytl0623 <[email protected]>
Signed-off-by: Dženan Zukić <[email protected]>
Signed-off-by: KumoLiu <[email protected]>
Signed-off-by: YunLiu <[email protected]>
Signed-off-by: Ishan Dutta <[email protected]>
Signed-off-by: dependabot[bot] <[email protected]>
Signed-off-by: kaibo <[email protected]>
Signed-off-by: heyufan1995 <[email protected]>
Signed-off-by: binliu <[email protected]>
Signed-off-by: axel.vlaminck <[email protected]>
Signed-off-by: Ibrahim Hadzic <[email protected]>
Signed-off-by: Behrooz <[email protected]>
Signed-off-by: Timothy Baker <[email protected]>
Signed-off-by: Mathijs de Boer <[email protected]>
Signed-off-by: Fabian Klopfer <[email protected]>
Signed-off-by: Lucas Robinet <[email protected]>
Signed-off-by: Lucas Robinet <[email protected]>
Signed-off-by: chaoliu <[email protected]>
Signed-off-by: cxlcl <[email protected]>
Signed-off-by: chaoliu <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: monai-bot <[email protected]>
Co-authored-by: elitap <[email protected]>
Co-authored-by: Felix Schnabel <[email protected]>
Co-authored-by: YanxuanLiu <[email protected]>
Co-authored-by: ytl0623 <[email protected]>
Co-authored-by: Dženan Zukić <[email protected]>
Co-authored-by: Eric Kerfoot <[email protected]>
Co-authored-by: YunLiu <[email protected]>
Co-authored-by: Ishan Dutta <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Kaibo Tang <[email protected]>
Co-authored-by: Yufan He <[email protected]>
Co-authored-by: binliunls <[email protected]>
Co-authored-by: Ben Murray <[email protected]>
Co-authored-by: axel.vlaminck <[email protected]>
Co-authored-by: Mingxin Zheng <[email protected]>
Co-authored-by: Ibrahim Hadzic <[email protected]>
Co-authored-by: Dr. Behrooz Hashemian <[email protected]>
Co-authored-by: Timothy J. Baker <[email protected]>
Co-authored-by: Mathijs de Boer <[email protected]>
Co-authored-by: Mathijs de Boer <[email protected]>
Co-authored-by: Fabian Klopfer <[email protected]>
Co-authored-by: Yiheng Wang <[email protected]>
Co-authored-by: Lucas Robinet <[email protected]>
Co-authored-by: Lucas Robinet <[email protected]>
Co-authored-by: cxlcl <[email protected]>
Signed-off-by: Dr. Behrooz Hashemian <[email protected]>
@drbeh
Copy link
Member

drbeh commented Apr 9, 2024

@NikolasSchmitz, I resolved the conflicts and updated the PR. Let's focus on the functionality and make this PR ready for reviewing. We can take care of any other issue once the PR is ready and please feel free to reach out to me or the working group if you still have any questions. Thanks for taking on this feature.

@NikolasSchmitz NikolasSchmitz marked this pull request as ready for review April 9, 2024 22:55
@NikolasSchmitz
Copy link
Author

Thank you @drbeh ! I now marked it as ready for review.

@ericspod ericspod requested a review from drbeh April 22, 2024 14:53

if within_tolerance:
# Take closest_level and continue with returning img at level
print(f"User-provided MPP lies within tolerance of level {closest_lvl}, returning wsi at this level.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Print statements generally shouldn't be in production code, if you want to keep track of things you can log this instead. This goes for all the other print statements below.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Eric, thanks for feedback!

@@ -940,6 +1054,91 @@ def get_mpp(self, wsi, level: int) -> tuple[float, float]:

raise ValueError("`mpp` cannot be obtained for this file. Please use `level` instead.")

def get_wsi_at_mpp(self, wsi, mpp: tuple, atol: float = 0.00, rtol: float = 0.05) -> np.ndarray:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code appears to duplicate a lot of that in the other get_wsi_at_mpp method. Can this be factored out into a separate function to eliminate the duplication?

@ericspod
Copy link
Member

@drbeh would you be able to review this? I think you're best qualified here. I made some minor comments about print and code duplication but otherwise it seems fine to me without having tested it. Thanks!

@JHancox JHancox self-assigned this May 14, 2024
Copy link
Contributor

@JHancox JHancox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the effort @NikolasSchmitz. A welcome addition! I agree with @ericspod about the refactoring to remove duplication - that would be great.

mpp_closest_lvl_x, mpp_closest_lvl_y = mpp_closest_lvl

# Define tolerance intervals for x and y of closest level
lower_bound_x = mpp_closest_lvl_x * (1 - rtol) - atol
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether the annotation ought to clarify the interaction between the absolute and relative tolerances. For example, someone might understandably assume that if either of the two values are exceeded then the value is deemed out of bounds, as opposed to the proposed behaviour which evaluates their combined tolerance.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could clarify the interaction of both tolerances in the function's docstrings. Additionally, to prevent the two values from exceeding a certain limit, we could implement a validation check that raises a ValueError if either value is out of bounds. I will implement it, and we can review and decide later if we want to adopt this approach.

target_res_x = int(np.round(closest_lvl_dim[1] * ds_factor_x))
target_res_y = int(np.round(closest_lvl_dim[0] * ds_factor_y))

closest_lvl_wsi = cucim_resize(wsi_arr, (target_res_x, target_res_y), order=0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think order=0 equates to nearest neighbour interpolation. The other methods seem to be using bilinear interpolation (order=1). If so, this would seem to be preferable. An alternative would be to have an optional parameter - possibly overkill.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, you're right. That should be order=1 here. Thanks!
If wanted, I could keep bilinear interpolation as default, and add an optional parameter to enable the user to overwrite the default. Potentially, the user might also want to decide on which resize method to use (currently cucim.skimage.transform.resize and PIL.Image.resize), which could be another optional parameter.

@NikolasSchmitz
Copy link
Author

Thank you for the feedback, @JHancox . Unfortunately, I couldn't join the meeting because I was on my way home from ICLR.
I will review the code and provide my updates as soon as possible.

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

Successfully merging this pull request may close these issues.

WSIReader support for reading by mpp or magnification
8 participants