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

ENH: Allow to also use resegmented mask for shape calculation #428

Merged
merged 1 commit into from
Sep 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions docs/customization.rst
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,21 @@ Feature Extractor Level

*Resegmentation*

- ``resegmentRange`` [None]: List of 2 floats, specifies the lower and upper threshold, respectively. Segmented voxels
outside this range are removed from the mask prior to feature calculation. When the value is None (default), no
resegmentation is performed. Resegemented size is checked (using parameter ``minimumROISize``, default 1) and upon
fail, an error is logged and the mask is reset to the original mask.

.. note::
This only affects first order and texture classes. No resegmentation is performed prior to calculating shape
features.
- ``resegmentRange`` [None]: List of 1 or 2 floats, specifies the lower and and optionally upper threshold,
respectively. Segmented voxels outside this range are removed from the mask prior to feature calculation. When the
value is None (default), no resegmentation is performed. Resegemented size is checked (using parameter
``minimumROISize``, default 1) and upon fail, an error is logged and extraction is skipped for this case.
- ``resegmentMode`` ['absolute']: string, specifying the method to use for defining the resegmentation thresholds:
- 'absolute': The resegmentRange values are treated as absolute values, i.e. used directly to perform resegmentation.
- 'relative': The resegmentRange values are treated as relative to the maximum in the ROI, i.e. the actual threshold
used is defined as :math:`\text{threshold} = \text{value} * X_{max}`.
- 'sigma': The resegmentRange values indicate a distance from the mean of the ROI in standard deviations. E.g. to
exclude outliers farther from the mean than 3 sigma, specify mode 'sigma' and range [-3, 3]. Threshold is defined as
:math:`\text{threshold} = \mu + \text{value} * \sigma`.
- ``resegmentShape`` [False]: Boolean, if set to True, the resegmented mask is also used for shape calculation. If set
to False (default), only first order and texture classes are calculated using the resegmented mask (known in IBSI as
the intensity mask). Shape is then calculated using the mask after any optional resampling and corrections (known in
IBSI as the morphologic mask).

*Mask validation*

Expand Down
12 changes: 10 additions & 2 deletions radiomics/featureextractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ def execute(self, imageFilepath, maskFilepath, label=None, voxelBased=False):
"""
geometryTolerance = self.settings.get('geometryTolerance')
additionalInfo = self.settings.get('additionalInfo', False)
resegmentShape = self.settings.get('resegmentShape', False)

if label is not None:
self.settings['label'] = label
else:
Expand Down Expand Up @@ -413,6 +415,11 @@ def execute(self, imageFilepath, maskFilepath, label=None, voxelBased=False):
if self.generalInfo is not None:
self.generalInfo.addMaskElements(image, resegmentedMask, label, 'resegmented')

# if resegmentShape is True and resegmentation has been enabled, update the mask here to also use the
# resegmented mask for shape calculation (e.g. PET resegmentation)
if resegmentShape and resegmentedMask is not None:
mask = resegmentedMask

if not voxelBased:
# 3. Add the additional information if enabled
if self.generalInfo is not None:
Expand All @@ -435,8 +442,9 @@ def execute(self, imageFilepath, maskFilepath, label=None, voxelBased=False):
newFeatureName = 'original_shape_%s' % featureName
featureVector[newFeatureName] = featureValue

# Only use resegemented mask for feature classes other than shape
if resegmentedMask is not None:
# (Default) Only use resegemented mask for feature classes other than shape
# can be overridden by specifying `resegmentShape` = True
if not resegmentShape and resegmentedMask is not None:
mask = resegmentedMask

# 6. Calculate other enabled feature classes using enabled image types
Expand Down
2 changes: 2 additions & 0 deletions radiomics/schemas/paramSchema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ mapping:
resegmentMode:
type: str
enum: ['absolute', 'relative', 'sigma']
resegmentShape:
type: bool
preCrop:
type: bool
sigma:
Expand Down