Repository: kymatio/kymatio

Issue:
Unexpected warning in 3D
With python=3.6, pytorch=1.0, and installing from sources, then doing "pytest", I obtain the following warning:

```
==================================================================================================== warnings summary ====================================================================================================
kymatio/scattering3d/tests/test_scattering3d.py::test_solid_harmonic_scattering
  /Users/oyallon/anaconda/envs/kymatio/lib/python3.6/site-packages/kymatio-0.1.0.dev0-py3.6.egg/kymatio/scattering3d/filter_bank.py:162: RuntimeWarning: invalid value encountered in sqrt
  /Users/oyallon/anaconda/envs/kymatio/lib/python3.6/site-packages/kymatio-0.1.0.dev0-py3.6.egg/kymatio/scattering3d/utils.py:105: RuntimeWarning: invalid value encountered in sqrt

kymatio/scattering3d/tests/test_scattering3d.py::test_larger_scales
  /Users/oyallon/anaconda/envs/kymatio/lib/python3.6/site-packages/kymatio-0.1.0.dev0-py3.6.egg/kymatio/scattering3d/filter_bank.py:162: RuntimeWarning: invalid value encountered in sqrt
  /Users/oyallon/anaconda/envs/kymatio/lib/python3.6/site-packages/kymatio-0.1.0.dev0-py3.6.egg/kymatio/scattering3d/utils.py:105: RuntimeWarning: invalid value encountered in sqrt

kymatio/scattering3d/tests/test_scattering3d.py::test_scattering_methods
  /Users/oyallon/anaconda/envs/kymatio/lib/python3.6/site-packages/kymatio-0.1.0.dev0-py3.6.egg/kymatio/scattering3d/filter_bank.py:162: RuntimeWarning: invalid value encountered in sqrt

-- Docs: https://docs.pytest.org/en/latest/warnings.html
========================================================================================= 29 passed, 5 warnings in 56.58 seconds =========================================================================================

```

Any suggestions?


Discussion:
Yeah I see that one too sometimes. It's not always there, though. Must be version-dependent.

Resolving patch:
diff --git a/kymatio/scattering3d/filter_bank.py b/kymatio/scattering3d/filter_bank.py
--- a/kymatio/scattering3d/filter_bank.py
+++ b/kymatio/scattering3d/filter_bank.py
@@ -8,7 +8,7 @@
 import torch
 import numpy as np
 from scipy.special import sph_harm, factorial
-from .utils import get_3d_angles, double_factorial
+from .utils import get_3d_angles, double_factorial, sqrt
 
 
 def solid_harmonic_filter_bank(M, N, O, J, L, sigma_0, fourier=True):
@@ -159,7 +159,7 @@ def solid_harmonic_3d(M, N, O, sigma, l, fourier=True):
         _sigma = 1. / sigma
 
     r_square = (grid ** 2).sum(0)
-    r_power_l = r_square ** (l / 2)
+    r_power_l = sqrt(r_square ** l)
     gaussian = np.exp(-0.5 * r_square / _sigma ** 2).astype('complex64')
 
     if l == 0:
diff --git a/kymatio/scattering3d/utils.py b/kymatio/scattering3d/utils.py
--- a/kymatio/scattering3d/utils.py
+++ b/kymatio/scattering3d/utils.py
@@ -1,6 +1,7 @@
 """Author: Louis Thiry, All rights reserved, 2018."""
 import torch
 import numpy as np
+import warnings
 
 
 def generate_weighted_sum_of_gaussians(grid, positions, weights, sigma,
@@ -102,7 +103,7 @@ def get_3d_angles(cartesian_grid):
     """
     z, y, x = cartesian_grid
     azimuthal = np.arctan2(y, x)
-    rxy = np.sqrt(x ** 2 + y ** 2)
+    rxy = sqrt(x ** 2 + y ** 2)
     polar = np.arctan2(z, rxy) + np.pi / 2
     return polar, azimuthal
 
@@ -110,3 +111,35 @@ def get_3d_angles(cartesian_grid):
 def double_factorial(i):
     """Computes the double factorial of an integer."""
     return 1 if (i < 1) else np.prod(np.arange(i, 0, -2))
+
+
+def sqrt(x):
+    """
+        Compute the square root of an array
+
+        This suppresses any warnings due to invalid input, unless the array is
+        real and has negative values. This fixes the erroneous warnings
+        introduced by an Intel SVM bug for large single-precision arrays. For
+        more information, see:
+
+            https://github.com/numpy/numpy/issues/11448
+            https://github.com/ContinuumIO/anaconda-issues/issues/9129
+
+        Parameters
+        ----------
+        x : numpy array
+            An array for which we would like to compute the square root.
+
+        Returns
+        -------
+        y : numpy array
+            The square root of the array.
+    """
+    if np.isrealobj(x) and (x < 0).any():
+        warnings.warn("Negative value encountered in sqrt", RuntimeWarning,
+            stacklevel=1)
+    old_settings = np.seterr(invalid='ignore')
+    y = np.sqrt(x)
+    np.seterr(**old_settings)
+
+    return y


Test patch:
diff --git a/kymatio/scattering3d/tests/test_scattering3d.py b/kymatio/scattering3d/tests/test_scattering3d.py
--- a/kymatio/scattering3d/tests/test_scattering3d.py
+++ b/kymatio/scattering3d/tests/test_scattering3d.py
@@ -3,9 +3,10 @@
 import os
 import warnings
 import numpy as np
+import pytest
 from kymatio import Scattering3D
 from kymatio.scattering3d import backend
-from kymatio.scattering3d.utils import generate_weighted_sum_of_gaussians, compute_integrals
+from kymatio.scattering3d.utils import generate_weighted_sum_of_gaussians, compute_integrals, sqrt
 
 if torch.cuda.is_available():
     devices = ['gpu', 'cpu']
@@ -175,3 +176,26 @@ def test_scattering_methods():
 
     Sx = scattering(x, method='local', points=points)
     Sx = scattering(x, method='local', points=points, rotation_covariant=False)
+
+def test_utils():
+    # Simple test
+    x = np.arange(8)
+    y = sqrt(x**2)
+    assert (y == x).all()
+
+    # Test problematic case
+    x = np.arange(8193, dtype='float32')
+    y = sqrt(x**2)
+    assert (y == x).all()
+
+    # Make sure we still don't let in negatives...
+    with pytest.warns(RuntimeWarning) as record:
+        x = np.array([-1, 0, 1])
+        y = sqrt(x)
+    assert "Negative" in record[0].message.args[0]
+
+    # ...unless they are compled numbers!
+    with pytest.warns(None) as record:
+        x = np.array([-1, 0, 1], dtype='complex64')
+        y = sqrt(x)
+    assert not record.list