Skip to content

Commit

Permalink
ENH: Add support for using a fixed bin count
Browse files Browse the repository at this point in the history
  • Loading branch information
JoostJM committed Jun 4, 2018
1 parent e6435e7 commit c92e23b
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 8 deletions.
10 changes: 9 additions & 1 deletion radiomics/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,17 @@ def __init__(self, inputImage, inputMask, **kwargs):
self.settings = kwargs

self.binWidth = kwargs.get('binWidth', 25)
# USE OF BINCOUNT IS NOT RECOMMENDED! See documentation/FAQ/Input-Customization for more details.
self.binCount = kwargs.get('binCount', None)
self.label = kwargs.get('label', 1)
self.voxelBased = kwargs.get('voxelBased', False)
self.initValue = kwargs.get('initValue', 0)

if self.binCount is not None:
self.logger.warning('Use of a fixed bin count is NOT RECOMMENDED! See '
'http://pyradiomics.readthedocs.io/en/latest/faq.html#'
'why-is-there-no-parameter-to-specify-a-fixed-bin-count for more details')

self.coefficients = {}

# all features are disabled by default
Expand Down Expand Up @@ -176,7 +183,8 @@ def _initCalculation(self):
def _applyBinning(self):
self.matrix, self.binEdges = imageoperations.binImage(self.binWidth,
self.imageArray,
self.maskArray)
self.maskArray,
self.settings.get('binCount', None))
self.coefficients['grayLevels'] = numpy.unique(self.matrix[self.maskArray])
self.coefficients['Ng'] = int(numpy.max(self.coefficients['grayLevels'])) # max gray level in the ROI

Expand Down
19 changes: 15 additions & 4 deletions radiomics/firstorder.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def __init__(self, inputImage, inputMask, **kwargs):
def _initCalculation(self):
super(RadiomicsFirstOrder, self)._initSegmentBasedCalculation()
self.targetVoxelArray = self.imageArray[self.labelledVoxelCoordinates].astype('float')
self.discretizedTargetVoxelArray = None # Lazy instantiation

self.logger.debug('First order feature class initialized')

Expand All @@ -52,6 +53,18 @@ def _moment(self, a, moment=1, axis=0):
s = numpy.power((a - mn), moment)
return numpy.mean(s, axis)

def _getDiscretizedTargetVoxelArray(self):
if self.discretizedTargetVoxelArray is None:
if self.binCount is not None:
self.logger.debug('Using fixed bin count of %d bins. NOT RECOMMENDED!!', self.binCount)
binEdges = self.binCount
else:
binEdges = imageoperations.getBinEdges(self.binWidth, self.targetVoxelArray)

self.discretizedTargetVoxelArray = numpy.histogram(self.targetVoxelArray, binEdges)[0]

return self.discretizedTargetVoxelArray

def getEnergyFeatureValue(self):
r"""
**1. Energy**
Expand Down Expand Up @@ -116,8 +129,7 @@ def getEntropyFeatureValue(self):
"""

eps = numpy.spacing(1)
binEdges = imageoperations.getBinEdges(self.binWidth, self.targetVoxelArray)
bins = numpy.histogram(self.targetVoxelArray, binEdges)[0]
bins = self._getDiscretizedTargetVoxelArray()

sumBins = bins.sum()
if sumBins == 0: # No segmented voxels
Expand Down Expand Up @@ -384,8 +396,7 @@ def getUniformityFeatureValue(self):
"""

eps = numpy.spacing(1)
binEdges = imageoperations.getBinEdges(self.binWidth, self.targetVoxelArray)
bins = numpy.histogram(self.targetVoxelArray, binEdges)[0]
bins = self._getDiscretizedTargetVoxelArray()
sumBins = bins.sum()

if sumBins == 0: # No segmented voxels
Expand Down
12 changes: 9 additions & 3 deletions radiomics/imageoperations.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def getBinEdges(binwidth, parameterValues):
return binEdges # numpy.histogram(parameterValues, bins=binedges)


def binImage(binwidth, parameterMatrix, parameterMatrixCoordinates=None):
def binImage(binwidth, parameterMatrix, parameterMatrixCoordinates=None, bincount=None):
r"""
Discretizes the parameterMatrix (matrix representation of the gray levels in the ROI) using the binEdges calculated
using :py:func:`getBinEdges`. Only voxels defined by parameterMatrixCoordinates (defining the segmentation) are used
Expand Down Expand Up @@ -84,10 +84,16 @@ def binImage(binwidth, parameterMatrix, parameterMatrixCoordinates=None):
logger.debug('Discretizing gray levels inside ROI')

if parameterMatrixCoordinates is None:
binEdges = getBinEdges(binwidth, parameterMatrix[:])
if bincount is not None:
binEdges = numpy.histogram(parameterMatrix[:], bincount)[1]
else:
binEdges = getBinEdges(binwidth, parameterMatrix[:])
parameterMatrix = numpy.digitize(parameterMatrix, binEdges)
else:
binEdges = getBinEdges(binwidth, parameterMatrix[parameterMatrixCoordinates])
if bincount is not None:
binEdges = numpy.histogram(parameterMatrix[parameterMatrixCoordinates], bincount)
else:
binEdges = getBinEdges(binwidth, parameterMatrix[parameterMatrixCoordinates])
parameterMatrix[parameterMatrixCoordinates] = numpy.digitize(parameterMatrix[parameterMatrixCoordinates], binEdges)

return parameterMatrix, binEdges
Expand Down
4 changes: 4 additions & 0 deletions radiomics/schemas/paramSchema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ mapping:
type: float
range:
min-ex: 0
binCount:
type: int
range:
min-ex: 0
normalize:
type: bool
normalizeScale:
Expand Down

0 comments on commit c92e23b

Please sign in to comment.