Skip to content

Commit

Permalink
updated roc tpr/fpr
Browse files Browse the repository at this point in the history
Former-commit-id: 3bb8db3
  • Loading branch information
ljchang committed Nov 6, 2017
2 parents e3d0f2b + a6054a8 commit 00809d9
Show file tree
Hide file tree
Showing 10 changed files with 316 additions and 123 deletions.
2 changes: 1 addition & 1 deletion nltools/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def calculate(self, input_values=None, binary_outcome=None,
if self.forced_choice is None:
self.threshold_type = threshold_type
if threshold_type == 'optimal_balanced':
mn = (tpr + fpr)/2
mn = (self.tpr+self.fpr)/2
self.class_thr = self.criterion_values[np.argmax(mn)]
elif threshold_type == 'optimal_overall':
n_corr_t = self.tpr*self.n_true
Expand Down
42 changes: 34 additions & 8 deletions nltools/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@
import os
import pickle # import cPickle
import nibabel as nib
from nltools.utils import get_resource_path, set_algorithm, get_anatomical, make_cosine_basis, glover_hrf
from nltools.utils import (get_resource_path,
set_algorithm,
get_anatomical,
make_cosine_basis,
glover_hrf)
from nltools.cross_validation import set_cv
from nltools.plotting import (dist_from_hyperplane_plot,
scatterplot,
Expand All @@ -36,14 +40,17 @@
fisher_r_to_z,
correlation_permutation,
one_sample_permutation,
two_sample_permutation)
two_sample_permutation,
downsample,
upsample,
zscore,
transform_pairwise)
from nltools.mask import expand_mask, collapse_mask
from nltools.stats import downsample, zscore, upsample
from nltools.analysis import Roc
from nilearn.input_data import NiftiMasker
from nilearn.image import resample_img
from nilearn.masking import intersect_masks
from nilearn.regions import connected_regions
from nilearn.regions import connected_regions, connected_label_regions
from nilearn.plotting.img_plotting import plot_epi, plot_roi, plot_stat_map
from nilearn.signal import clean
from copy import deepcopy
Expand Down Expand Up @@ -190,6 +197,7 @@ def __getitem__(self, index):
if isinstance(index, int):
new.data = np.array(self.data[index, :]).flatten()
else:
index = np.array(index).flatten()
new.data = np.array(self.data[index, :])
if not self.Y.empty:
new.Y = self.Y.iloc[index]
Expand Down Expand Up @@ -544,7 +552,7 @@ def similarity(self, image, method='correlation'):

if not isinstance(image, Brain_Data):
if isinstance(image, nib.Nifti1Image):
image = Brain_Data(image)
image = Brain_Data(image, mask=self.mask)
else:
raise ValueError("Image is not a Brain_Data or nibabel "
"instance")
Expand Down Expand Up @@ -1312,7 +1320,7 @@ def threshold(self, thresh=0, binarize=False):
return b

def regions(self, min_region_size=1350, extract_type='local_regions',
smoothing_fwhm=6):
smoothing_fwhm=6, is_mask=False):
''' Extract brain connected regions into separate regions.
Args:
Expand All @@ -1332,16 +1340,34 @@ def regions(self, min_region_size=1350, extract_type='local_regions',
smoothing_fwhm (scalar): Smooth an image to extract more sparser
regions. Only works for extract_type
'local_regions'.
is_mask (bool): Whether the Brain_Data instance should be treated as a boolean mask and if so, calls connected_label_regions instead.
Returns:
Brain_Data: Brain_Data instance with extracted ROIs as data.
'''

regions, _ = connected_regions(self.to_nifti(),
if is_mask:
regions, _ = connected_label_regions(self.to_nifti())
else:
regions, _ = connected_regions(self.to_nifti(),
min_region_size, extract_type,
smoothing_fwhm)
return Brain_Data(regions)

return Brain_Data(regions, mask=self.mask)

def transform_pairwise(self):
''' Extract brain connected regions into separate regions.
Args:
Returns:
Brain_Data: Brain_Data instance tranformed into pairwise comparisons
'''
out = self.copy()
out.data, new_Y = transform_pairwise(self.data,self.Y)
out.Y = pd.DataFrame(new_Y)
out.Y.replace(-1,0,inplace=True)
return out

class Adjacency(object):

Expand Down
65 changes: 27 additions & 38 deletions nltools/mask.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
import numpy as np
import warnings
from nilearn.masking import intersect_masks
# from neurosynth.masks import Masker


def create_sphere(coordinates, radius=5, mask=None):
""" Generate a set of spheres in the brain mask space
Expand All @@ -35,8 +33,8 @@ def create_sphere(coordinates, radius=5, mask=None):
from nltools.data import Brain_Data

if mask is not None:
if not isinstance(mask,nib.Nifti1Image):
if type(mask) is str:
if not isinstance(mask, nib.Nifti1Image):
if isinstance(mask, six.string_types):
if os.path.isfile(mask):
data = nib.load(mask)
else:
Expand All @@ -57,48 +55,38 @@ def sphere(r, p, mask):
"""
dims = mask.shape
m = [dims[0]/2, dims[1]/2, dims[2]/2] # JC edit: default value for centers
x, y, z = np.ogrid[-m[0]:dims[0]-m[0], -m[1]:dims[1]-m[1], -m[2]:dims[2]-m[2]] #JC edit: creates sphere
# x, y, z = np.ogrid[-p[0]:dims[0]-p[0], -p[1]:dims[1]-p[1], -p[2]:dims[2]-p[2]]
m = [dims[0]/2, dims[1]/2, dims[2]/2]
x, y, z = np.ogrid[-m[0]:dims[0]-m[0],
-m[1]:dims[1]-m[1],
-m[2]:dims[2]-m[2]]
mask_r = x*x + y*y + z*z <= r*r

activation = np.zeros(dims)
activation[mask_r] = 1
# JC edit shift mask to proper location
translation_affine= np.array([[1, 0, 0, p[0]-m[0]],
translation_affine = np.array([[1, 0, 0, p[0]-m[0]],
[0, 1, 0, p[1]-m[1]],
[0, 0, 1, p[2]-m[2]],
[0, 0, 0, 1]])

# activation = np.multiply(activation, mask.get_data())
# activation = nib.Nifti1Image(activation, affine=np.eye(4))
activation = nib.Nifti1Image(activation, affine=translation_affine)
#return the 3D numpy matrix of zeros containing the sphere as a region of ones
# return activation.get_data(), translation_affine
return activation

# Initialize Spheres with options for multiple radii and centers of the spheres (or just an int and a 3D list)
# return sphere(radius,coordinates,mask)
if type(radius) is int:
radius = [radius]
if coordinates is None:
coordinates = [[dims[0]/2, dims[1]/2, dims[2]/2] * len(radius)] #default value for centers
elif type(coordinates) is list and type(coordinates[0]) is int and len(radius) is 1:
coordinates = [coordinates]
if (type(radius)) is list and (type(coordinates) is list) and (len(radius) == len(coordinates)):
A = np.zeros_like(mask.get_data())
A = Brain_Data(nib.Nifti1Image(A, affine=mask.affine), mask=mask)
for i in range(len(radius)):
A = A + Brain_Data(sphere(radius[i], coordinates[i], mask),
mask=mask)
A = A.to_nifti()
A.get_data()[A.get_data()>0.5]=1
A.get_data()[A.get_data()<0.5]=0
return A
return nib.Nifti1Image(activation, affine=translation_affine)

if any(isinstance(i, list) for i in coordinates):
if isinstance(radius, list):
if len(radius) != len(coordinates):
raise ValueError('Make sure length of radius list matches'
'length of coordinate list.')
elif isinstance(radius, int):
radius = [radius]*len(coordinates)
out = Brain_Data(nib.Nifti1Image(np.zeros_like(mask.get_data()),
affine=mask.affine), mask=mask)
for r, c in zip(radius, coordinates):
out = out + Brain_Data(sphere(r, c, mask), mask=mask)
else:
raise ValueError("Data type for sphere or radius(ii) or center(s) "
"not recognized.")

out = Brain_Data(sphere(radius, coordinates, mask), mask=mask)
out = out.to_nifti()
out.get_data()[out.get_data() > 0.5]=1
out.get_data()[out.get_data() < 0.5]=0
return out

def expand_mask(mask):
""" expand a mask with multiple integers into separate binary masks
Expand Down Expand Up @@ -160,7 +148,8 @@ def collapse_mask(mask, auto_label=True):

merge = []
if auto_label:
# Combine all masks into sequential order ignoring any areas of overlap
# Combine all masks into sequential order
# ignoring any areas of overlap
for i in range(len(m_list)):
merge.append(np.multiply(
Brain_Data(m_list[i]).data,
Expand Down
12 changes: 8 additions & 4 deletions nltools/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from nltools.stats import two_sample_permutation
from nilearn.plotting import plot_glass_brain, plot_stat_map

def plotTBrain(objIn,how='full',thr='unc',alpha=None,nperm=None,**kwargs):
def plotTBrain(objIn,how='full',thr='unc',alpha=None,nperm=None, cut_coords = [],**kwargs):
"""
Takes a brain data object and computes a 1 sample t-test across it's first axis. If a list is provided will compute difference between brain data objects in list (i.e. paired samples t-test).
Args:
Expand All @@ -37,12 +37,16 @@ def plotTBrain(objIn,how='full',thr='unc',alpha=None,nperm=None,**kwargs):
thr: (str) what method to use for multiple comparisons correction unc, fdr, or tfce
alpha: (float) p-value threshold
nperm: (int) number of permutations for tcfe; default 1000
cut_coords: (list) x,y,z coords to plot brain slice
kwargs: optionals args to nilearn plot functions (e.g. vmax)
"""
assert thr in ['unc','fdr','tfce'], "Acceptable threshold methods are 'unc','fdr','tfce'"
views = ['x','y','z']
coords = [range(-40,50,10),[-88,-72,-58,-38,-26,8,20,34,46],[-34,-22,-10,0,16,34,46,56,66]]
if len(cut_coords) == 0:
cut_coords = [range(-40,50,10),[-88,-72,-58,-38,-26,8,20,34,46],[-34,-22,-10,0,16,34,46,56,66]]
else:
assert(len(cut_coords)==3), 'cut_coords must be a list of coordinates like [[xs],[ys],[zs]]'
cmap = 'RdBu_r'

if type(objIn) == list:
Expand Down Expand Up @@ -81,12 +85,12 @@ def plotTBrain(objIn,how='full',thr='unc',alpha=None,nperm=None,**kwargs):

if how == 'full':
plot_glass_brain(obj.to_nifti(),display_mode='lzry',colorbar=True,cmap=cmap,plot_abs=False,**kwargs)
for v,c in zip(views,coords):
for v,c in zip(views,cut_coords):
plot_stat_map(obj.to_nifti(), cut_coords = c, display_mode = v,cmap=cmap,**kwargs)
elif how == 'glass':
plot_glass_brain(obj.to_nifti(),display_mode='lzry',colorbar=True,cmap=cmap,plot_abs=False,**kwargs)
elif how == 'mni':
for v,c in zip(views,coords):
for v,c in zip(views,cut_coords):
plot_stat_map(obj.to_nifti(), cut_coords = c, display_mode = v,cmap=cmap,**kwargs)
del obj
del out
Expand Down
Loading

0 comments on commit 00809d9

Please sign in to comment.