Skip to content

Commit

Permalink
camel-cased routines in radiomics modules, updated documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
adityaapte committed Jun 24, 2024
1 parent fd8b65c commit 04f89ad
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 120 deletions.
3 changes: 2 additions & 1 deletion cerr/plan_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ def get_empty_list():
class PlanC:
"""Plan Container for imaging metadata. Each Attribute of this class holds metadata for a particular type
of imaging object. Additional attributes can be added to this class without breaking the functionality
fom other attributes.
from other attributes.
Attributes:
header (cerr.dataclasses.header.Header): Header storing information about date of creation, version etc.
scan (List[cerr.dataclasses.scan.Scan]): List of pyCERR's scan objects for modalities such as CT, MR, PT or derived types.
Expand Down
2 changes: 1 addition & 1 deletion cerr/radiomics/first_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import cerr.plan_container as pc
from cerr.utils.statistics import quantile, prctile

def radiomics_first_order_stats(planC, structNum, offsetForEnergy=0, binWidth=None, binNum=None):
def stats(planC, structNum, offsetForEnergy=0, binWidth=None, binNum=None):
"""
This routine calculates 1st order statistical features from the input image and segmentation based on
Expand Down
12 changes: 6 additions & 6 deletions cerr/radiomics/ibsi1.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,17 @@ def calcRadiomicsForImgType(volToEval, maskBoundingBox3M, morphMask3M, gridS, pa

# Shape features
if 'shape' in paramS['featureClass'] and paramS['featureClass']['shape']["featureList"] != {}:
from cerr.radiomics.shape import compute_shape_features
featDict['shape'] = compute_shape_features(morphMask3M,gridS['xValsV'],gridS['yValsV'],gridS['zValsV'])
from cerr.radiomics.shape import calcShapeFeatures
featDict['shape'] = calcShapeFeatures(morphMask3M, gridS['xValsV'], gridS['yValsV'], gridS['zValsV'])

# Assign nan values outside the mask, so that min/max within the mask are used for quantization
volToEval[~maskBoundingBox3M] = np.nan

# Texture-based scalar features
if 'texture' in paramS['settings']:
# Quantization
quantized3M = preprocess.imquantize_cerr(volToEval, num_level=textureBinNum,\
xmin=minClipIntensity, xmax=maxClipIntensity, binwidth=textureBinWidth)
quantized3M = preprocess.imquantize(volToEval, num_level=textureBinNum, \
xmin=minClipIntensity, xmax=maxClipIntensity, binwidth=textureBinWidth)
nL = quantized3M.max()

if any(name in ['glcm','glrlm','glszm'] for name in paramS['featureClass'].keys()):
Expand All @@ -122,8 +122,8 @@ def calcRadiomicsForImgType(volToEval, maskBoundingBox3M, morphMask3M, gridS, pa
if 'firstOrder' in paramS['featureClass'] and paramS['featureClass']['firstOrder']["featureList"] != {}:
voxelVol = np.prod(gridS["PixelSpacingV"]) * 1000 # units of mm
scanV = volToEval[maskBoundingBox3M]
featDict['firstOrder'] = first_order.radiomics_first_order_stats(scanV, voxelVol,
firstOrderOffsetEnergy, firstOrderEntropyBinWidth, firstOrderEntropyBinNum)
featDict['firstOrder'] = first_order.stats(scanV, voxelVol,
firstOrderOffsetEnergy, firstOrderEntropyBinWidth, firstOrderEntropyBinNum)

# GLCM
if 'glcm' in paramS['featureClass'] and paramS['featureClass']['glcm']["featureList"] != {}:
Expand Down
2 changes: 1 addition & 1 deletion cerr/radiomics/preprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# from scipy.ndimage import generate_binary_structure
# from scipy.interpolate import RegularGridInterpolator

def imquantize_cerr(x, num_level=None, xmin=None, xmax=None, binwidth=None):
def imquantize(x, num_level=None, xmin=None, xmax=None, binwidth=None):
"""
Function to quantize an image based on the number of bins (num_level) or the bin width (bin_width).
Expand Down
85 changes: 1 addition & 84 deletions cerr/radiomics/run_length.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
This module contains routines for claculation of Run Length texture features
This module contains routines for calculation of Run Length texture features
"""

import numpy as np
Expand Down Expand Up @@ -102,89 +102,6 @@ def calcRLM(quantizedM, offsetsM, nL, rlmType=1):
return rlmOut


##### ======= Matlab implementation that uses np.roll (circshift)
def calcRLM_old(quantizedM, offsetsM, nL, rlmType=1):
if rlmType != 1:
rlmOut = []

pad_width = [(1, 1)] * quantizedM.ndim
quantizedM = np.pad(quantizedM, pad_width, mode='constant', constant_values=0)

numRowsPad, numColsPad, numSlcsPad = 1, 1, 1
q = np.pad(quantizedM, ((numRowsPad, numRowsPad), (numColsPad, numColsPad), (numSlcsPad, numSlcsPad)),
mode='constant', constant_values=0)
q[np.isnan(q)] = 0
q = q.astype(np.uint16)

numOffsets = offsetsM.shape[0]
maxRunLen = int(np.ceil(np.max(quantizedM.shape)*2))
#maxRunLen = 1000
print('Max Run Length = ' + str(maxRunLen))

rlmM = np.zeros((nL, maxRunLen))
if rlmType == 2:
rlmOut = [np.zeros((nL, maxRunLen)) for i in range(numOffsets)]

#lenV = np.zeros(np.prod(q.shape), dtype = np.uint16)

siz = q.shape

for off in range(numOffsets):
if rlmType == 2:
rlmM = rlmOut[off]

offset = offsetsM[off]

for level in range(1, nL + 1):
#t = time.time()
prevM = (q == level).astype(int)
#diffM = (q == level).astype(int) - (np.roll(q, offset, axis=(0, 1, 2)) == level).astype(int)
diffM = prevM - np.roll(prevM, offset, axis=(0, 1, 2))
startM = diffM == 1
startIndV = np.where(startM)

#prevM = (q == level).astype(np.uint16)
prevM = prevM.astype(np.uint16)
convergedM = ~startM

#elapsed = time.time() - t
#print('Level start = ' + str(level) + '. Time = ' + str(elapsed))
#t = time.time()

#lenV *= 0
#start = 0
while not np.all(convergedM):
nextM = np.roll(prevM, -offset, axis=(0, 1, 2))
addM = prevM + nextM
newConvergedM = (addM == prevM)
toUpdateM = ~convergedM & newConvergedM
prevM = nextM
prevM[startIndV] = addM[startIndV]
lenV = addM[toUpdateM]
# if len(lenV) > 0:
# countsV = np.bincount(lenV)
# numCounts = len(countsV) - 1
# rlmM[level - 1, :numCounts] = rlmM[level - 1, :numCounts] + countsV[1:]
if len(lenV) > 0:
rlmM[level - 1, :] = rlmM[level - 1, :] + np.bincount(lenV, minlength=maxRunLen+1)[1:]
#stop = start + len(addM[toUpdateM])
#lenV[start:stop] = addM[toUpdateM]
#start = stop
convergedM = convergedM | newConvergedM
#rlmM[level - 1, :] = np.bincount(lenV[:stop], minlength=maxRunLen+1)[1:]
#elapsed = time.time() - t
#print('Level end = ' + str(level) + '. Time = ' + str(elapsed))

if rlmType == 2:
#rlmOut.append(rlmM)
rlmOut[off] = rlmM

if rlmType == 1:
rlmOut = rlmM

return rlmOut


def rlmToScalarFeatures(rlmM, numVoxels):
"""
Expand Down
6 changes: 3 additions & 3 deletions cerr/radiomics/shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def trimeshSurfaceArea(v,f):

return area

def vector_norm3d(v):
def vectorNorm3d(v):
return np.linalg.norm(v, axis=1)

def eig(a):
Expand All @@ -50,7 +50,7 @@ def calcMaxDistBetweenPts(ptsM, distType):
distType (str or Callable): Type of distance. E.g. 'euclidean' as supported by scipy.spatial.distance.cdist
Returns:
float: Maximim distance between the input points
float: Maximum distance between the input points
"""

dmax = 0
Expand All @@ -75,7 +75,7 @@ def calcMaxDistBetweenPts(ptsM, distType):

return dmax

def compute_shape_features(mask3M, xValsV, yValsV, zValsV):
def calcShapeFeatures(mask3M, xValsV, yValsV, zValsV):
"""Routine to calculate shape features for the inout mask and grid
Args:
Expand Down
Binary file modified docs/_build/doctrees/cerr.doctree
Binary file not shown.
50 changes: 26 additions & 24 deletions docs/cerr.rst
Original file line number Diff line number Diff line change
@@ -1,38 +1,15 @@
cerr package
============

Subpackages
-----------

.. toctree::
:maxdepth: 4

cerr.contour
cerr.dataclasses
cerr.datasets
cerr.dcm_export
cerr.radiomics
cerr.registration
cerr.roe
cerr.utils

Submodules
----------

cerr.dvh module
---------------

.. automodule:: cerr.dvh
:members:
:undoc-members:
:show-inheritance:

cerr.plan\_container module
---------------------------

.. automodule:: cerr.plan_container
:members:
:undoc-members:
:exclude-members: json_serialize
:show-inheritance:

cerr.viewer module
Expand All @@ -43,6 +20,31 @@ cerr.viewer module
:undoc-members:
:show-inheritance:

cerr.dvh module
---------------

.. automodule:: cerr.dvh
:members:
:undoc-members:
:show-inheritance:


Subpackages
-----------

.. toctree::
:maxdepth: 4

cerr.contour
cerr.dataclasses
cerr.datasets
cerr.dcm_export
cerr.radiomics
cerr.registration
cerr.roe
cerr.utils


Module contents
---------------

Expand Down

0 comments on commit 04f89ad

Please sign in to comment.