Skip to content

Commit

Permalink
Merge pull request #337 from JoostJM/add-voxel-based-calculation
Browse files Browse the repository at this point in the history
ADD: Add voxel-based extraction
  • Loading branch information
JoostJM authored Jun 4, 2018
2 parents 1b0eb74 + 233b486 commit e6435e7
Show file tree
Hide file tree
Showing 18 changed files with 682 additions and 493 deletions.
17 changes: 17 additions & 0 deletions examples/exampleSettings/exampleVoxel.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

imageType:
Original: {}

featureClass:
glcm:
- JointEntropy

setting:
binWidth: 25
force2D: true
label: 1

voxelSetting:
kernelRadius: 2
maskedKernel: true
initValue: nan
28 changes: 14 additions & 14 deletions examples/helloFeatureClass.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@
print(getattr(firstOrderFeatures, 'get%sFeatureValue' % f).__doc__)

print('Calculating first order features...')
firstOrderFeatures.calculateFeatures()
results = firstOrderFeatures.execute()
print('done')

print('Calculated first order features: ')
for (key, val) in six.iteritems(firstOrderFeatures.featureValues):
for (key, val) in six.iteritems(results):
print(' ', key, ':', val)

#
Expand All @@ -79,11 +79,11 @@
print(getattr(shapeFeatures, 'get%sFeatureValue' % f).__doc__)

print('Calculating Shape features...')
shapeFeatures.calculateFeatures()
results = shapeFeatures.execute()
print('done')

print('Calculated Shape features: ')
for (key, val) in six.iteritems(shapeFeatures.featureValues):
for (key, val) in six.iteritems(results):
print(' ', key, ':', val)

#
Expand All @@ -98,11 +98,11 @@
print(getattr(glcmFeatures, 'get%sFeatureValue' % f).__doc__)

print('Calculating GLCM features...')
glcmFeatures.calculateFeatures()
results = glcmFeatures.execute()
print('done')

print('Calculated GLCM features: ')
for (key, val) in six.iteritems(glcmFeatures.featureValues):
for (key, val) in six.iteritems(results):
print(' ', key, ':', val)

#
Expand All @@ -117,11 +117,11 @@
print(getattr(glrlmFeatures, 'get%sFeatureValue' % f).__doc__)

print('Calculating GLRLM features...')
glrlmFeatures.calculateFeatures()
results = glrlmFeatures.execute()
print('done')

print('Calculated GLRLM features: ')
for (key, val) in six.iteritems(glrlmFeatures.featureValues):
for (key, val) in six.iteritems(results):
print(' ', key, ':', val)

#
Expand All @@ -136,11 +136,11 @@
print(getattr(glszmFeatures, 'get%sFeatureValue' % f).__doc__)

print('Calculating GLSZM features...')
glszmFeatures.calculateFeatures()
results = glszmFeatures.execute()
print('done')

print('Calculated GLSZM features: ')
for (key, val) in six.iteritems(glszmFeatures.featureValues):
for (key, val) in six.iteritems(results):
print(' ', key, ':', val)

#
Expand All @@ -151,8 +151,8 @@
for logImage, imageTypeName, inputKwargs in imageoperations.getLoGImage(image, mask, sigma=sigmaValues):
logFirstorderFeatures = firstorder.RadiomicsFirstOrder(logImage, mask, **inputKwargs)
logFirstorderFeatures.enableAllFeatures()
logFirstorderFeatures.calculateFeatures()
for (key, val) in six.iteritems(logFirstorderFeatures.featureValues):
results = logFirstorderFeatures.execute()
for (key, val) in six.iteritems(results):
laplacianFeatureName = '%s_%s' % (imageTypeName, key)
print(' ', laplacianFeatureName, ':', val)
#
Expand All @@ -162,8 +162,8 @@
for decompositionImage, decompositionName, inputKwargs in imageoperations.getWaveletImage(image, mask):
waveletFirstOrderFeaturs = firstorder.RadiomicsFirstOrder(decompositionImage, mask, **inputKwargs)
waveletFirstOrderFeaturs.enableAllFeatures()
waveletFirstOrderFeaturs.calculateFeatures()
results = waveletFirstOrderFeaturs.execute()
print('Calculated firstorder features with wavelet ', decompositionName)
for (key, val) in six.iteritems(waveletFirstOrderFeaturs.featureValues):
for (key, val) in six.iteritems(results):
waveletFeatureName = '%s_%s' % (str(decompositionName), key)
print(' ', waveletFeatureName, ':', val)
117 changes: 117 additions & 0 deletions examples/helloVoxel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#!/usr/bin/env python

from __future__ import print_function

import logging
import os

import SimpleITK as sitk
import six

import radiomics
from radiomics import featureextractor

def tqdmProgressbar():
"""
This function will setup the progress bar exposed by the 'tqdm' package.
Progress reporting is only used in PyRadiomics for the calculation of GLCM and GLSZM in full python mode, therefore
enable GLCM and full-python mode to show the progress bar functionality
N.B. This function will only work if the 'click' package is installed (not included in the PyRadiomics requirements)
"""
global extractor

radiomics.setVerbosity(logging.INFO) # Verbosity must be at least INFO to enable progress bar

import tqdm
radiomics.progressReporter = tqdm.tqdm

def clickProgressbar():
"""
This function will setup the progress bar exposed by the 'click' package.
Progress reporting is only used in PyRadiomics for the calculation of GLCM and GLSZM in full python mode, therefore
enable GLCM and full-python mode to show the progress bar functionality.
Because the signature used to instantiate a click progress bar is different from what PyRadiomics expects, we need to
write a simple wrapper class to enable use of a click progress bar. In this case we only need to change the 'desc'
keyword argument to a 'label' keyword argument.
N.B. This function will only work if the 'click' package is installed (not included in the PyRadiomics requirements)
"""
global extractor

# Enable the GLCM class to show the progress bar
extractor.enableFeatureClassByName('glcm')

radiomics.setVerbosity(logging.INFO) # Verbosity must be at least INFO to enable progress bar

import click

class progressWrapper():
def __init__(self, iterable, desc=''):
# For a click progressbar, the description must be provided in the 'label' keyword argument.
self.bar = click.progressbar(iterable, label=desc)

def __iter__(self):
return self.bar.__iter__() # Redirect to the __iter__ function of the click progressbar

def __enter__(self):
return self.bar.__enter__() # Redirect to the __enter__ function of the click progressbar

def __exit__(self, exc_type, exc_value, tb):
return self.bar.__exit__(exc_type, exc_value, tb) # Redirect to the __exit__ function of the click progressbar

radiomics.progressReporter = progressWrapper

# Get some test data
testCase = 'lung2'
# repositoryRoot points to the root of the repository. The following line gets that location if this script is run
# from it's default location in \pyradiomics\bin. Otherwise, it will point to some (invalid) folder, causing the
# getTestCase function to fail to find the test case in the repository. In that case, a test case will be downloaded to
# temporary files and it's location is returned.
repositoryRoot = os.path.abspath(os.path.join(os.getcwd(), ".."))
imageName, maskName = radiomics.getTestCase(testCase, repositoryRoot)

# Get the location of the example settings file
paramsFile = os.path.abspath(r'exampleSettings\exampleVoxel.yaml')

if imageName is None or maskName is None: # Something went wrong, in this case PyRadiomics will also log an error
print('Error getting testcase!')
exit()

# Regulate verbosity with radiomics.verbosity
# radiomics.setVerbosity(logging.INFO)

# Get the PyRadiomics logger (default log-level = INFO
logger = radiomics.logger
logger.setLevel(logging.DEBUG) # set level to DEBUG to include debug log messages in log file

# Write out all log entries to a file
handler = logging.FileHandler(filename='testLog.txt', mode='w')
formatter = logging.Formatter("%(levelname)s:%(name)s: %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)

# Initialize feature extractor using the settings file
extractor = featureextractor.RadiomicsFeaturesExtractor(paramsFile)

# Uncomment one of these functions to show how PyRadiomics can use the 'tqdm' or 'click' package to report progress when
# running in full python mode. Assumes the respective package is installed (not included in the requirements)

tqdmProgressbar()
# clickProgressbar()

print("Active features:")
for cls, features in six.iteritems(extractor._enabledFeatures):
if len(features) == 0:
features = [f for f, deprecated in six.iteritems(extractor.getFeatureNames(cls)) if not deprecated]
for f in features:
print(f)
print(getattr(extractor.featureClasses[cls], 'get%sFeatureValue' % f).__doc__)

print("Calculating features")
featureVector = extractor.execute(imageName, maskName, voxelBased=True)

for featureName in featureVector.keys():
sitk.WriteImage(featureVector[featureName], '%s_%s.nrrd' % (testCase, featureName))
print('Computed %s, stored as "%s_%s.nrrd"' % (featureName, testCase, featureName))
Loading

0 comments on commit e6435e7

Please sign in to comment.