@@ -1185,31 +1185,61 @@ def is_outlier(points, thresh=3.5):
11851185 return timepoints_to_discard
11861186
11871187
1188- def cosine_filter (
1189- data , timestep , period_cut , remove_mean = True , axis = - 1 , failure_mode = "error"
1188+ def _make_cosine_regressors (ntimepoints , timestep , period_cut ):
1189+ return _full_rank (_cosine_drift (period_cut , timestep * np .arange (ntimepoints )))[0 ]
1190+
1191+
1192+ def _make_legendre_regressors (ntimepoints , degree ):
1193+ X = np .ones ((ntimepoints , 1 )) # quick way to calc degree 0
1194+ for i in range (degree ):
1195+ polynomial_func = Legendre .basis (i + 1 )
1196+ value_array = np .linspace (- 1 , 1 , ntimepoints )
1197+ X = np .hstack ((X , polynomial_func (value_array )[:, np .newaxis ]))
1198+ return X
1199+
1200+
1201+ def _high_pass_filter (
1202+ data , * args , filter_type , remove_mean = True , axis = - 1 , failure_mode = "error"
11901203):
11911204 datashape = data .shape
11921205 timepoints = datashape [axis ]
11931206 if datashape [0 ] == 0 and failure_mode != "error" :
11941207 return data , np .array ([])
11951208
1196- data = data .reshape ((- 1 , timepoints ))
1209+ filters = {
1210+ 'cosine' : _make_cosine_regressors ,
1211+ 'legendre' : _make_legendre_regressors ,
1212+ }
11971213
1198- frametimes = timestep * np .arange (timepoints )
1199- X = _full_rank (_cosine_drift (period_cut , frametimes ))[0 ]
1214+ X = filters [filter_type ](timepoints , * args )
12001215 non_constant_regressors = X [:, :- 1 ] if X .shape [1 ] > 1 else np .array ([])
12011216
1202- betas = np .linalg .lstsq (X , data .T )[0 ]
1217+ data = data .reshape ((- 1 , timepoints ))
1218+
1219+ betas = np .linalg .pinv (X ) @ data .T
12031220
12041221 if not remove_mean :
12051222 X = X [:, :- 1 ]
12061223 betas = betas [:- 1 ]
12071224
1208- residuals = data - X .dot (betas ).T
1209-
1225+ residuals = data - (X @ betas ).T
12101226 return residuals .reshape (datashape ), non_constant_regressors
12111227
12121228
1229+ def cosine_filter (
1230+ data , timestep , period_cut , remove_mean = True , axis = - 1 , failure_mode = "error"
1231+ ):
1232+ return _high_pass_filter (
1233+ data ,
1234+ timestep ,
1235+ period_cut ,
1236+ filter_type = 'cosine' ,
1237+ remove_mean = remove_mean ,
1238+ axis = axis ,
1239+ failure_mode = failure_mode ,
1240+ )
1241+
1242+
12131243def regress_poly (degree , data , remove_mean = True , axis = - 1 , failure_mode = "error" ):
12141244 """
12151245 Returns data with degree polynomial regressed out.
@@ -1221,36 +1251,14 @@ def regress_poly(degree, data, remove_mean=True, axis=-1, failure_mode="error"):
12211251 IFLOGGER .debug (
12221252 "Performing polynomial regression on data of shape %s" , str (data .shape )
12231253 )
1224-
1225- datashape = data .shape
1226- timepoints = datashape [axis ]
1227- if datashape [0 ] == 0 and failure_mode != "error" :
1228- return data , np .array ([])
1229-
1230- # Rearrange all voxel-wise time-series in rows
1231- data = data .reshape ((- 1 , timepoints ))
1232-
1233- # Generate design matrix
1234- X = np .ones ((timepoints , 1 )) # quick way to calc degree 0
1235- for i in range (degree ):
1236- polynomial_func = Legendre .basis (i + 1 )
1237- value_array = np .linspace (- 1 , 1 , timepoints )
1238- X = np .hstack ((X , polynomial_func (value_array )[:, np .newaxis ]))
1239-
1240- non_constant_regressors = X [:, :- 1 ] if X .shape [1 ] > 1 else np .array ([])
1241-
1242- # Calculate coefficients
1243- betas = np .linalg .pinv (X ).dot (data .T )
1244-
1245- # Estimation
1246- if remove_mean :
1247- datahat = X .dot (betas ).T
1248- else : # disregard the first layer of X, which is degree 0
1249- datahat = X [:, 1 :].dot (betas [1 :, ...]).T
1250- regressed_data = data - datahat
1251-
1252- # Back to original shape
1253- return regressed_data .reshape (datashape ), non_constant_regressors
1254+ return _high_pass_filter (
1255+ data ,
1256+ degree ,
1257+ filter_type = 'legendre' ,
1258+ remove_mean = remove_mean ,
1259+ axis = axis ,
1260+ failure_mode = failure_mode ,
1261+ )
12541262
12551263
12561264def combine_mask_files (mask_files , mask_method = None , mask_index = None ):
0 commit comments