Skip to content

Commit

Permalink
ENH: Adding brains module
Browse files Browse the repository at this point in the history
ENH: Added segmentation volume support

ENH: Added posterior volume support
  • Loading branch information
dmwelch committed Jan 29, 2013
1 parent 8b43db3 commit de46620
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 0 deletions.
9 changes: 9 additions & 0 deletions AutoWorkup/brains/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
__version__ = 'beta'
#import config
#import metrics

def check_file(filename):
import os.path
fullName = os.path.abspath(filename)
assert os.path.exists(fullName), "File %s cannot be found!" % fullName
return fullName
4 changes: 4 additions & 0 deletions AutoWorkup/brains/config/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from ConfigParser import SafeConfigParser as scp
_config = scp()

from autoworkup import *
19 changes: 19 additions & 0 deletions AutoWorkup/brains/config/autoworkup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from . import _config

valid_schemes = ['BRAINS', 'Nipype']

def writeConfiguration(filename='example.config'):
config = ConfigParser.SafeConfigParser()
config.add_section("Results")
config.set("Results", "directory", "/full/path/to/experiment/directory")
config.set("Results", "segmentations", "SingleRFSegmentations")
config.set("Results", "posteriors", "TissueClassify")
config.set("Results", "scheme", "BRAINS")
with open(filename, 'wb') as configfile:
config.write(configfile)


def loadConfiguration(configFile='/dev/null'):
_config.read(configFile)

#_config = loadConfiguration()
5 changes: 5 additions & 0 deletions AutoWorkup/brains/metrics/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from ..config import loadConfiguration
from segmentations import *
from partials import *


101 changes: 101 additions & 0 deletions AutoWorkup/brains/metrics/partials.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import numpy as np
import os.path
from warnings import warn

import SimpleITK as sitk

from ..config import _config

posteriors = ['accumben', 'air', 'caudate', 'crblgm', 'crblwm', 'csf', 'globus', 'hippocampus', 'notcsf', 'notgm', 'notvb', 'notwm', 'putamen', 'surfgm', 'thalamus', 'vb', 'wm']
_tolerance = [0.99, 1.01]
_tolerance_wm = [0.99, 1.01]


def _formatPosteriorAssertString():
assertString = "Posterior label is not recognized: %s\nValid labels are:"
for p in posteriors:
assertString = '\n'.join([assertString, p.upper() + ','])
assertString = assertString[:-1]
return assertString


def _checkPosteriorLabel(label):
errorString = _formatPosteriorAssertString()
assert label.lower() in posteriors, errorString % label


def calculateBinaryVolume(dirname, label):
label = label.upper()
_checkPosteriorLabel(label)
labelFile = os.path.join(dirname, 'POSTERIOR_'+ label + '.nii.gz')
assert os.path.exists(labelFile), "File not found: %s" % labelFile
image = sitk.ReadImage(labelFile)
if label == 'WM':
lowerTol, upperTol = _tolerance_wm
warn("Using lower threshold of %g for white matter binary calculations." % lowerTol)
else:
lowerTol, upperTol = _tolerance
binary = sitk.BinaryThreshold(image, lowerTol, upperTol, 1, 0)
nda = sitk.GetArrayFromImage(binary)
maskSum = nda.sum()
## print maskSum
size = image.GetSpacing()
## print size
return maskSum * size[0] * size[1] * size[2]


def calculatePartialVolume(dirname, label):
label = label.upper()
_checkPosteriorLabel(label)
labelFile = os.path.join(dirname, 'POSTERIOR_' + label + '.nii.gz')
assert os.path.exists(labelFile), "File not found: %s" % labelFile
image = sitk.ReadImage(labelFile)
nda = sitk.GetArrayFromImage(image)
maskSum = nda.sum()
## print maskSum
size = image.GetSpacing()
## print size
return maskSum * size[0] * size[1] * size[2]


def getPartialVolume(args=[], kwds={}):
dirname = labels = project = subject = session = experimentDir = None
experimentDir = _config.get('Results', 'directory')
partialsDir = _config.get('Results', 'posteriors')
for key, value in kwds:
if key == 'dirname':
dirname = check_file(value)
elif key == 'labels':
labels = value
elif key == 'project':
project = value
elif key == 'subject':
subject = value
elif key == 'session':
session = value
if session is None:
session = args.pop()
if subject is None:
subject = args.pop()
if project is None:
project = args.pop()
if labels is None:
labels = args
if dirname is None:
try:
dirname = os.path.join(experimentDir, project, subject, session, partialsDir)
except Exception, err:
raise err
### DEBUGGING ###
#print labels
#print dirname
#print project
#print subject
#print session
### END DEBUG ###
# labels = map(formatLabel, labels) # convert shorthand to human-readable
volume = 0.0
for label in labels:
volume += calculateBinaryVolume(dirname, label)
return volume

90 changes: 90 additions & 0 deletions AutoWorkup/brains/metrics/segmentations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import numpy as np
import os.path

import SimpleITK as sitk

from ..config import _config
labels = ['caudate', 'putamen', 'hippocampus', 'thalamus', 'accumben', 'globus']

def constructLabels(labels):
numbers = range(1,((len(labels)*2) + 1))
full_labels = []
index = 0
for label in labels:
full_labels.append('_'.join(['left', label]))
full_labels.append('_'.join(['right', label]))
return full_labels, numbers

def _moduleCreateLabels(labels):
full_labels, numbers = constructLabels(labels)
labelMap = map(None, full_labels, numbers)
return dict(labelMap) # Use this variable


def formatLabel(label):
"""
Assumes that the label can be split by the '_' character.
"""
side, anatomy = label.split('_')
if side.lower() in ['l', 'left']:
side = 'left'
elif side.lower() in ['r', 'right']:
side = 'right'
else:
raise ValueError('Label %s is not recognized: cannot determine side %s' % (label, side))
label = '_'.join([side,anatomy])
return label


def calculateLabelVolume(dirname, label):
labelFile = os.path.join(dirname, _config.get('Results', 'segmentations'), label + '_seg.nii.gz')
assert os.path.exists(labelFile), "File not found: %s" % labelFile
image = sitk.ReadImage(labelFile)
nda = sitk.GetArrayFromImage(image)
maskSum = nda.sum()
print maskSum
size = image.GetSpacing()
print size
return maskSum * size[0] * size[1] * size[2]


def getVolume(args=[], kwds={}):
dirname = labels = project = subject = session = experimentDir = None
experimentDir = _config.get('Results', 'directory') ### HACK
for key, value in kwds:
if key == 'dirname':
dirname = check_file(value)
elif key == 'labels':
labels = value
elif key == 'project':
project = value
elif key == 'subject':
subject = value
elif key == 'session':
session = value
if session is None:
session = args.pop()
if subject is None:
subject = args.pop()
if project is None:
project = args.pop()
if labels is None:
labels = args
if dirname is None:
try:
# config needs to be accessible
dirname = os.path.join(experimentDir, project, subject, session)
except Exception, err:
raise err
### DEBUGGING ###
#print labels
#print dirname
#print project
#print subject
#print session
### END DEBUG ###
# labels = map(formatLabel, labels) # convert shorthand to human-readable
volume = 0.0
for label in labels:
volume += calculateLabelVolume(dirname, label)
return volume

0 comments on commit de46620

Please sign in to comment.