From b60c8cefeb380a1e49f8b76803d6f4f0c61f0896 Mon Sep 17 00:00:00 2001 From: Feilong Ma Date: Fri, 21 Dec 2018 11:41:35 -0500 Subject: [PATCH 1/3] Resolve LinAlgError during SVD The default `lapack_driver` uses randomized SVD, which occasionally will cause `LinAlgError` even if the data are completely fine. Switching `lapack_driver` to `gesvd` will solve this issue. --- nipype/algorithms/confounds.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/nipype/algorithms/confounds.py b/nipype/algorithms/confounds.py index a5feb89925..a132de70bc 100644 --- a/nipype/algorithms/confounds.py +++ b/nipype/algorithms/confounds.py @@ -14,6 +14,7 @@ import nibabel as nb import numpy as np from numpy.polynomial import Legendre +from scipy import linalg from .. import config, logging from ..external.due import BibTeX @@ -1193,9 +1194,12 @@ def compute_noise_components(imgseries, mask_images, num_components, try: u, _, _ = np.linalg.svd(M, full_matrices=False) except np.linalg.LinAlgError: - if self.inputs.failure_mode == 'error': - raise - u = np.ones((M.shape[0], num_components), dtype=np.float32) * np.nan + try: + u, _, _ = linalg.svd(M, full_matrices=False, lapack_driver='gesvd') + except linalg.LinAlgError: + if self.inputs.failure_mode == 'error': + raise + u = np.ones((M.shape[0], num_components), dtype=np.float32) * np.nan if components is None: components = u[:, :num_components] else: From 09f3b2783528b81f9b69916c6a0b510cb327aa9e Mon Sep 17 00:00:00 2001 From: Ma Feilong Date: Fri, 21 Dec 2018 17:05:05 -0500 Subject: [PATCH 2/3] Refactor try/except to function. --- nipype/algorithms/confounds.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/nipype/algorithms/confounds.py b/nipype/algorithms/confounds.py index a132de70bc..81f298595f 100644 --- a/nipype/algorithms/confounds.py +++ b/nipype/algorithms/confounds.py @@ -27,6 +27,16 @@ IFLOGGER = logging.getLogger('nipype.interface') +def fallback_svd(a, full_matrices=True, compute_uv=True): + try: + return np.linalg.svd(a, full_matrices=full_matrices, compute_uv=compute_uv) + except np.linalg.LinAlgError: + pass + + from scipy.linalg import svd + return svd(a, full_matrices=full_matrices, compute_uv=compute_uv, lapack_driver='gesvd') + + class ComputeDVARSInputSpec(BaseInterfaceInputSpec): in_file = File( exists=True, mandatory=True, desc='functional data, after HMC') @@ -1192,14 +1202,11 @@ def compute_noise_components(imgseries, mask_images, num_components, # "The covariance matrix C = MMT was constructed and decomposed into its # principal components using a singular value decomposition." try: - u, _, _ = np.linalg.svd(M, full_matrices=False) + u, _, _ = fallback_svd(M, full_matrices=False) except np.linalg.LinAlgError: - try: - u, _, _ = linalg.svd(M, full_matrices=False, lapack_driver='gesvd') - except linalg.LinAlgError: - if self.inputs.failure_mode == 'error': - raise - u = np.ones((M.shape[0], num_components), dtype=np.float32) * np.nan + if self.inputs.failure_mode == 'error': + raise + u = np.ones((M.shape[0], num_components), dtype=np.float32) * np.nan if components is None: components = u[:, :num_components] else: @@ -1277,7 +1284,7 @@ def _full_rank(X, cmax=1e15): X: array of shape(nrows, ncols) after regularization cmax=1.e-15, float tolerance for condition number """ - U, s, V = np.linalg.svd(X, 0) + U, s, V = fallback_svd(X, full_matrices=False) smax, smin = s.max(), s.min() c = smax / smin if c < cmax: From 053fd616b431847c9877288158ddfa374d182002 Mon Sep 17 00:00:00 2001 From: Ma Feilong Date: Fri, 21 Dec 2018 17:12:24 -0500 Subject: [PATCH 3/3] Remove unnecessary import. --- nipype/algorithms/confounds.py | 1 - 1 file changed, 1 deletion(-) diff --git a/nipype/algorithms/confounds.py b/nipype/algorithms/confounds.py index 81f298595f..79c0b96f4e 100644 --- a/nipype/algorithms/confounds.py +++ b/nipype/algorithms/confounds.py @@ -14,7 +14,6 @@ import nibabel as nb import numpy as np from numpy.polynomial import Legendre -from scipy import linalg from .. import config, logging from ..external.due import BibTeX