Skip to content

Commit e33b572

Browse files
authored
Merge pull request #356 from cosanlab/srm
added isfc
2 parents b81d947 + 8b59b86 commit e33b572

File tree

7 files changed

+286
-107
lines changed

7 files changed

+286
-107
lines changed

nltools/data/adjacency.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
two_sample_permutation,
2727
summarize_bootstrap,
2828
matrix_permutation,
29-
jackknife_permutation,
3029
fisher_r_to_z,
3130
_calc_pvalue,
3231
_bootstrap_isc)
@@ -390,8 +389,8 @@ def plot(self, limit=3, axes=None, *args, **kwargs):
390389
''' Create Heatmap of Adjacency Matrix
391390
392391
Can pass in any sns.heatmap argument
393-
394-
Args:
392+
393+
Args:
395394
limit: (int) number of heatmaps to plot if object contains multiple adjacencies (default: 3)
396395
axes: matplotlib axis handle
397396
'''
@@ -576,7 +575,7 @@ def similarity(self, data, plot=False, perm_type='2d', n_permute=5000,
576575
Default is to use spearman correlation and permutation test.
577576
Args:
578577
data: Adjacency data, or 1-d array same size as self.data
579-
perm_type: (str) '1d','2d', 'jackknife', or None
578+
perm_type: (str) '1d','2d', or None
580579
metric: (str) 'spearman','pearson','kendall'
581580
ignore_diagonal: (bool) only applies to 'directed' Adjacency types using perm_type=None or perm_type='1d'
582581
'''
@@ -593,10 +592,8 @@ def similarity(self, data, plot=False, perm_type='2d', n_permute=5000,
593592
similarity_func = correlation_permutation
594593
elif perm_type == '2d':
595594
similarity_func = matrix_permutation
596-
elif perm_type == 'jackknife':
597-
similarity_func = jackknife_permutation
598595
else:
599-
raise ValueError("perm_type must be ['1d','2d', 'jackknife', or None']")
596+
raise ValueError("perm_type must be ['1d','2d', or None']")
600597

601598
def _convert_data_similarity(data, perm_type=None, ignore_diagonal=ignore_diagonal):
602599
'''Helper function to convert data correctly'''
@@ -606,13 +603,13 @@ def _convert_data_similarity(data, perm_type=None, ignore_diagonal=ignore_diagon
606603
data = d[~np.eye(d.shape[0]).astype(bool)]
607604
else:
608605
data = data.data
609-
elif perm_type in ['2d', 'jackknife']:
606+
elif perm_type == '2d':
610607
if not data.issymmetric:
611608
raise TypeError(f"data must be symmetric to do {perm_type} permutation")
612609
else:
613610
data = data.squareform()
614611
else:
615-
raise ValueError("perm_type must be ['1d','2d', 'jackknife', or None']")
612+
raise ValueError("perm_type must be ['1d','2d', or None']")
616613
return data
617614

618615
if self.is_single_matrix:

nltools/data/brain_data.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from scipy.stats import ttest_1samp, pearsonr
1919
from scipy.stats import t as t_dist
2020
from scipy.signal import detrend
21+
from scipy.interpolate import pchip
2122
import os
2223
import shutil
2324
import nibabel as nib
@@ -1887,6 +1888,41 @@ def find_spikes(self, global_spike_cutoff=3, diff_spike_cutoff=3):
18871888
global_spike_cutoff=global_spike_cutoff,
18881889
diff_spike_cutoff=diff_spike_cutoff)
18891890

1891+
def temporal_resample(self, sampling_freq=None, target=None, target_type='hz'):
1892+
''' Resample Brain_Data timeseries to a new target frequency or number of samples
1893+
using Piecewise Cubic Hermite Interpolating Polynomial (PCHIP) interpolation.
1894+
This function can up- or down-sample data.
1895+
1896+
Note: this function can use quite a bit of RAM.
1897+
1898+
Args:
1899+
sampling_freq: (float) sampling frequency of data in hertz
1900+
target: (float) upsampling target
1901+
target_type: (str) type of target can be [samples,seconds,hz]
1902+
1903+
Returns:
1904+
upsampled Brain_Data instance
1905+
'''
1906+
1907+
out = self.copy()
1908+
1909+
if target_type == 'samples':
1910+
n_samples = target
1911+
elif target_type == 'seconds':
1912+
n_samples = target*sampling_freq
1913+
elif target_type == 'hz':
1914+
n_samples = float(sampling_freq)/float(target)
1915+
else:
1916+
raise ValueError('Make sure target_type is "samples", "seconds", or "hz".')
1917+
1918+
orig_spacing = np.arange(0, self.shape()[0], 1)
1919+
new_spacing = np.arange(0, self.shape()[0], n_samples)
1920+
1921+
out.data = np.zeros([len(new_spacing), self.shape()[1]])
1922+
for i in range(self.shape()[1]):
1923+
interpolate = pchip(orig_spacing, self.data[:, i])
1924+
out.data[:, i] = interpolate(new_spacing)
1925+
return out
18901926

18911927
class Groupby(object):
18921928
def __init__(self, data, mask):

nltools/mask.py

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ def create_sphere(coordinates, radius=5, mask=None):
4343
else:
4444
raise ValueError("mask is not a nibabel instance or a valid "
4545
"file name")
46+
4647
else:
4748
mask = nib.load(resolve_mni_path(MNI_Template)['mask'])
4849

@@ -182,33 +183,19 @@ def roi_to_brain(data, mask_x):
182183
Args:
183184
data: Pandas series, dataframe, list, np.array of ROI by observation
184185
mask_x: an expanded binary mask
186+
185187
Returns:
186188
out: (Brain_Data) Brain_Data instance where each ROI is now populated
187189
with a value
188190
'''
189191
from nltools.data import Brain_Data
190192

191-
def series_to_brain(data, mask_x):
192-
'''Converts a pandas series of ROIs to a Brain_Data instance. Index must correspond to ROI index'''
193-
194-
if not isinstance(data, pd.Series):
195-
raise ValueError('Data must be a pandas series')
196-
if len(mask_x) != len(data):
197-
raise ValueError('Data must have the same number of rows as mask has ROIs.')
198-
return Brain_Data([mask_x[x]*data[x] for x in data.keys()]).sum()
199-
200193
if not isinstance(data, (pd.Series, pd.DataFrame)):
201194
if isinstance(data, list):
202-
if len(data) != len(mask_x):
203-
raise ValueError('Data must have the same number of rows as mask has ROIs.')
204-
else:
205-
data = pd.Series(data)
195+
data = pd.Series(data)
206196
elif isinstance(data, np.ndarray):
207197
if len(data.shape) == 1:
208-
if len(data) != len(mask_x):
209-
raise ValueError('Data must have the same number of rows as mask has ROIs.')
210-
else:
211-
data = pd.Series(data)
198+
data = pd.Series(data)
212199
elif len(data.shape) == 2:
213200
data = pd.DataFrame(data)
214201
if data.shape[0] != len(mask_x):
@@ -220,15 +207,17 @@ def series_to_brain(data, mask_x):
220207
raise NotImplementedError
221208

222209
else:
223-
raise NotImplementedError
224-
210+
raise ValueError("Data must be a pandas series or data frame.")
225211

226212
if len(mask_x) != data.shape[0]:
227213
raise ValueError('Data must have the same number of rows as mask has ROIs.')
228214

229215
if isinstance(data, pd.Series):
230-
return series_to_brain(data, mask_x)
231-
elif isinstance(data, pd.DataFrame):
232-
return Brain_Data([series_to_brain(data[x], mask_x) for x in data.keys()])
216+
return Brain_Data([mask_x[x]*data[x] for x in data.keys()]).sum()
233217
else:
234-
raise ValueError("Data must be a pandas series or data frame.")
218+
out = mask_x.copy()
219+
out.data = np.ones((data.shape[1], out.data.shape[1]))
220+
for roi in range(len(mask_x)):
221+
roi_data = np.reshape(data.iloc[roi,:].values, (-1,1))
222+
out.data[:, mask_x[roi].data==1] = np.repeat(roi_data.T, np.sum(mask_x[roi].data==1), axis=0).T
223+
return out

0 commit comments

Comments
 (0)