diff --git a/tedana/decomposition/ica.py b/tedana/decomposition/ica.py index a309709b8..7e4902ecb 100644 --- a/tedana/decomposition/ica.py +++ b/tedana/decomposition/ica.py @@ -161,7 +161,7 @@ def r_ica(data, n_components, fixed_seed, n_robust_runs, max_it): robust_ica = RobustICA( n_components=n_components, robust_runs=n_robust_runs, - whiten="arbitrary-variance", + whiten="unit-variance", max_iter=max_it, random_state=fixed_seed, robust_dimreduce=False, @@ -320,6 +320,7 @@ def f_ica(data, n_components, fixed_seed, maxit, maxrestart): n_components=n_components, algorithm="parallel", fun="logcosh", + whiten="unit-variance", max_iter=maxit, random_state=fixed_seed, ) diff --git a/tedana/decomposition/pca.py b/tedana/decomposition/pca.py index 24ac3181e..0c066b196 100644 --- a/tedana/decomposition/pca.py +++ b/tedana/decomposition/pca.py @@ -60,6 +60,7 @@ def tedpca( kdaw=10.0, rdaw=1.0, low_mem=False, + mean_center_only=False, ): r"""Use principal components analysis (PCA) to identify and remove thermal noise from data. @@ -104,6 +105,9 @@ def tedpca( Whether to use incremental PCA (for low-memory systems) or not. This is only compatible with the "kundu" or "kundu-stabilize" algorithms. Default: False + mean_center_only : :obj:`bool`, optional + Only center the mean time series to 0 instead of also scaling the variance + Default: False Returns ------- @@ -210,8 +214,13 @@ def tedpca( ) data = data_optcom[mask, :] - data_z = ((data.T - data.T.mean(axis=0)) / data.T.std(axis=0)).T # var normalize ts - data_z = (data_z - data_z.mean()) / data_z.std() # var normalize everything + if mean_center_only: + LGR.info("Mean centering data before PCA") + data_z = data - data.mean(axis=1, keepdims=True) # mean normalize ts + else: + LGR.info("Z scaling data before PCA") + data_z = ((data.T - data.T.mean(axis=0)) / data.T.std(axis=0)).T # var normalize ts + data_z = (data_z - data_z.mean()) / data_z.std() # var normalize everything if algorithm in ["mdl", "aic", "kic"]: data_img = io.new_nii_like(io_generator.reference_img, utils.unmask(data, mask)) @@ -450,7 +459,12 @@ def tedpca( voxel_kept_comp_weighted = voxel_comp_weights[:, acc] * varex[None, acc] kept_data = np.dot(voxel_kept_comp_weighted, comp_ts[:, acc].T) - kept_data = stats.zscore(kept_data, axis=1) # variance normalize time series - kept_data = stats.zscore(kept_data, axis=None) # variance normalize everything + if mean_center_only: + LGR.info("Mean centering data before ICA") + kept_data = kept_data - np.mean(kept_data, axis=1, keepdims=True) + else: + LGR.info("Z scaling data before ICA") + kept_data = stats.zscore(kept_data, axis=1) # variance normalize time series + kept_data = stats.zscore(kept_data, axis=None) # variance normalize everything return kept_data, n_components diff --git a/tedana/workflows/tedana.py b/tedana/workflows/tedana.py index 56110593b..2be6a122c 100644 --- a/tedana/workflows/tedana.py +++ b/tedana/workflows/tedana.py @@ -369,6 +369,15 @@ def _get_parser(): default=None, ) + optional.add_argument( + "--mean_center_only", + "--mean-center-only", + dest="mean_center_only", + action="store_false", + help="Only mean center fMRI time series before PCA and ICA. Do not scale by stdev.", + default=False, + ) + optional.add_argument( "--quiet", dest="quiet", help=argparse.SUPPRESS, action="store_true", default=False ) @@ -431,6 +440,7 @@ def tedana_workflow( t2smap=None, mixing_file=None, tedana_command=None, + mean_center_only=False, ): """Run the "canonical" TE-Dependent ANAlysis workflow. @@ -549,6 +559,9 @@ def tedana_workflow( mixing_file : :obj:`str` or None, optional File containing mixing matrix, to be used when re-running the workflow. If not provided, ME-PCA and ME-ICA are done. Default is None. + mean_center_only : :obj:`bool`, optional + Only center the mean time series to 0 instead of also scaling the variance + Default: False quiet : :obj:`bool`, optional If True, suppresses logging/printing of messages. Default is False. overwrite : :obj:`bool`, optional @@ -840,6 +853,7 @@ def tedana_workflow( kdaw=10.0, rdaw=1.0, low_mem=low_mem, + mean_center_only=mean_center_only, ) if verbose: io_generator.save_file(utils.unmask(data_reduced, mask_clf), "whitened img")