AIM-Harvard / pyradiomics

Open-source python package for the extraction of Radiomics features from 2D and 3D images and binary masks. Support: https://discourse.slicer.org/c/community/radiomics
http://pyradiomics.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
1.15k stars 499 forks source link

checkMask will always fail if mask and image geometry do not match #251

Closed fedorov closed 7 years ago

fedorov commented 7 years ago

checkMask essentially expects that image and mask geometry will match by calling Execute here: https://github.com/Radiomics/pyradiomics/blob/master/radiomics/imageoperations.py#L201

Thanks to Dev Gude for identifying and reporting this issue!

fedorov commented 7 years ago

@Radiomics/developers let's discuss this tomorrow at the call

JoostJM commented 7 years ago

In featureextractor.py, checkMask is called after the image is loaded (includes any resampling): https://github.com/Radiomics/pyradiomics/blob/master/radiomics/featureextractor.py#L402

It is indeed true that this causes the extraction to fail if image and mask geometry do not match at this point. I programmed it like this to prevent features from being extracted from invalid image/mask combinations.

However, if resampling is enabled, there is a different type of checking done: https://github.com/Radiomics/pyradiomics/blob/master/radiomics/imageoperations.py#L325

This piece of code is part of the resampling and checks if the ROI defined in the maskNode encodes for a physical space that is contained within the supplied image. If this is the case, the resampling grid is defined using the maskNode and applied to both mask and image, which ensures matching geometry.

So in short: if no resampling is enabled checkMask will fail when geometry does not match, but this is intended as such to prevent invalid combinations from being used. If resampling is enabled, it is only required that the ROI in the mask encodes a tumor in the physical space contained by the image, with the resampling itself ensuring that then the geometry also matches up.

fedorov commented 7 years ago

@JoostJM thanks for the clarifications!

  1. I quickly looked over the user manual, and didn't find the place that explains how to enable resampling. Can you point me to that place in text? I think it would be good to link that from the FAQ entry.

  2. Would it make more sense to print the error message and suggest that user could try resampling the mask instead of crashing with the exception?

JoostJM commented 7 years ago

@fedorov Good points! I will try to have a PR ready before the meeting tomorrow!

fedorov commented 7 years ago

Great, thanks!

I think it will be very helpful to the user to provide more fine-grained diagnostics to troubleshoot the issue. These 2 will be very common, and very easy to troubleshoot, situations:

  1. Problem: origin/spacing/directions differ by small amount. Solution: increase epsilon in the config file (assuming it is exposed) or enable resampling.

  2. Problem: FOV is different, but mask FOV is inside the image FOV. Solution: enable resampling.

JoostJM commented 7 years ago

@fedorov @ Problem 1: Yes epsilon's exposed as a global field (part of processobject) I'll see what I can do, shouldn't be to difficult...