Coverage for nilearn/decomposition/_multi_pca.py: 30%

21 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-20 10:58 +0200

1"""PCA dimension reduction on multiple subjects. 

2 

3This is a good initialization method for ICA. 

4""" 

5 

6import numpy as np 

7from sklearn.utils.extmath import randomized_svd 

8 

9from nilearn._utils import fill_doc 

10 

11from ._base import _BaseDecomposition 

12 

13 

14@fill_doc 

15class _MultiPCA(_BaseDecomposition): 

16 """Perform Multi Subject Principal Component Analysis. 

17 

18 Perform a PCA on each subject, stack the results, and reduce them 

19 at group level. An optional Canonical Correlation Analysis can be 

20 performed at group level. This is a good initialization method for ICA. 

21 

22 Parameters 

23 ---------- 

24 n_components : int, default=20 

25 Number of components to extract. 

26 

27 do_cca : boolean, default=True 

28 Indicate if a Canonical Correlation Analysis must be run after the 

29 PCA. 

30 

31 %(random_state)s 

32 

33 %(smoothing_fwhm)s 

34 

35 mask : Niimg-like object, :obj:`~nilearn.maskers.NiftiMasker` or \ 

36 :obj:`~nilearn.maskers.MultiNiftiMasker` or \ 

37 :obj:`~nilearn.surface.SurfaceImage` or \ 

38 :obj:`~nilearn.maskers.SurfaceMasker` object, optional 

39 Mask to be used on data. If an instance of masker is passed, 

40 then its mask will be used. If no mask is given, for Nifti images, 

41 it will be computed automatically by a MultiNiftiMasker with default 

42 parameters; for surface images, all the vertices will be used. 

43 

44 %(mask_strategy)s 

45 Default='epi'. 

46 .. note:: 

47 

48 These strategies are only relevant for Nifti images and the parameter 

49 is ignored for SurfaceImage objects. 

50 

51 mask_args : dict, optional 

52 If mask is None, these are additional parameters passed to 

53 :func:`nilearn.masking.compute_background_mask`, 

54 or :func:`nilearn.masking.compute_epi_mask` 

55 to fine-tune mask computation. 

56 Please see the related documentation for details. 

57 

58 standardize : boolean, default=False 

59 If standardize is True, the time-series are centered and normed: 

60 their mean is put to 0 and their variance to 1 in the time dimension. 

61 

62 standardize_confounds : boolean, default=True 

63 If standardize_confounds is True, the confounds are z-scored: 

64 their mean is put to 0 and their variance to 1 in the time dimension. 

65 

66 detrend : boolean, default=False 

67 If detrend is True, the time-series will be detrended before 

68 components extraction. 

69 

70 %(target_affine)s 

71 

72 .. note:: 

73 This parameter is passed to :func:`nilearn.image.resample_img`. 

74 

75 %(target_shape)s 

76 

77 .. note:: 

78 This parameter is passed to :func:`nilearn.image.resample_img`. 

79 

80 %(low_pass)s 

81 

82 .. note:: 

83 This parameter is passed to :func:`nilearn.image.resample_img`. 

84 

85 %(high_pass)s 

86 

87 .. note:: 

88 This parameter is passed to :func:`nilearn.image.resample_img`. 

89 

90 %(t_r)s 

91 

92 .. note:: 

93 This parameter is passed to :func:`nilearn.image.resample_img`. 

94 

95 memory : instance of joblib.Memory or string, default=None 

96 Used to cache the masking process. 

97 By default, no caching is done. 

98 If a string is given, it is the path to the caching directory. 

99 If ``None`` is passed will default to ``Memory(location=None)``. 

100 

101 memory_level : integer, default=0 

102 Rough estimator of the amount of memory used by caching. Higher value 

103 means more memory for caching. 

104 

105 n_jobs : integer, default=1 

106 The number of CPUs to use to do the computation. -1 means 

107 'all CPUs', -2 'all CPUs but one', and so on. 

108 

109 %(verbose0)s 

110 

111 %(base_decomposition_attributes)s 

112 

113 %(multi_pca_attributes)s 

114 

115 """ 

116 

117 def __init__( 

118 self, 

119 n_components=20, 

120 mask=None, 

121 smoothing_fwhm=None, 

122 do_cca=True, 

123 random_state=None, 

124 standardize=False, 

125 standardize_confounds=True, 

126 detrend=False, 

127 low_pass=None, 

128 high_pass=None, 

129 t_r=None, 

130 target_affine=None, 

131 target_shape=None, 

132 mask_strategy="epi", 

133 mask_args=None, 

134 memory=None, 

135 memory_level=0, 

136 n_jobs=1, 

137 verbose=0, 

138 ): 

139 super().__init__( 

140 n_components=n_components, 

141 random_state=random_state, 

142 mask=mask, 

143 smoothing_fwhm=smoothing_fwhm, 

144 standardize=standardize, 

145 standardize_confounds=standardize_confounds, 

146 detrend=detrend, 

147 low_pass=low_pass, 

148 high_pass=high_pass, 

149 t_r=t_r, 

150 target_affine=target_affine, 

151 target_shape=target_shape, 

152 mask_strategy=mask_strategy, 

153 mask_args=mask_args, 

154 memory=memory, 

155 memory_level=memory_level, 

156 n_jobs=n_jobs, 

157 verbose=verbose, 

158 ) 

159 

160 self.do_cca = do_cca 

161 

162 def _raw_fit(self, data): 

163 """Process unmasked data directly.""" 

164 if self.do_cca: 

165 S = np.sqrt(np.sum(data**2, axis=1)) 

166 S[S == 0] = 1 

167 data /= S[:, np.newaxis] 

168 components_, self.variance_, _ = self._cache( 

169 randomized_svd, func_memory_level=2 

170 )( 

171 data.T, 

172 n_components=self.n_components, 

173 transpose=True, 

174 random_state=self.random_state, 

175 n_iter=3, 

176 ) 

177 if self.do_cca: 

178 data *= S[:, np.newaxis] 

179 self.components_ = components_.T 

180 if hasattr(self, "masker_"): 

181 self.components_img_ = self.masker_.inverse_transform( 

182 components_.T 

183 ) 

184 return components_