Repository: jason-neal/eniric

Issue:
Rotation of vsini=0.
**Describe the bug**
A `vsini=0` returns a Zero division error in rotation kernel.

  ```
File "/data/jneal/Code/repos/eniric/eniric/broaden.py", line 437, in rotation_kernel
    c1 = 2.0 * (1.0 - epsilon) / denominator
ZeroDivisionError: float division by zero

```

**To Reproduce**
Attempting rotational convolution with vsini=0.


**Expected behavior**
A rotation of 0 should leave the lines unbroadend so should be skipped.

Could also just try then check for ZeroDivisionError.


Discussion:

Patch:
diff --git a/eniric/broaden.py b/eniric/broaden.py
index 94d2900..04cd4e3 100644
--- a/eniric/broaden.py
+++ b/eniric/broaden.py
@@ -6,16 +6,16 @@ Used to convolve the spectra for
 
 Uses joblib.Memory to cache convolution results to skip repeated computation.
 """
-from typing import Optional, Union
 import os
+from typing import Optional, Union
 
-import numpy as np
 import multiprocess as mprocess
+import numpy as np
 from astropy.constants import c
 from joblib import Memory
+from multiprocess import pool
 from numpy.core.multiarray import ndarray
 from tqdm import tqdm
-from multiprocess import pool
 
 import eniric
 from eniric.utilities import band_selector, mask_between, wav_selector
@@ -113,33 +113,42 @@ def rotational_convolution(
 
         return sum_val
 
-    tqdm_wav = tqdm(wavelength, disable=not verbose)
-
-    if num_procs is None:
-        num_procs = num_procs_minus_1
-
-    if isinstance(num_procs, int):
-        if num_procs not in [0, 1]:
-            with mprocess.Pool(processes=num_procs) as mproc_pool:
+    if vsini != 0:
+        tqdm_wav = tqdm(wavelength, disable=not verbose)
+
+        if num_procs is None:
+            num_procs = num_procs_minus_1
+
+        if isinstance(num_procs, int):
+            if num_procs not in [0, 1]:
+                with mprocess.Pool(processes=num_procs) as mproc_pool:
+                    convolved_flux = np.array(
+                        mproc_pool.map(element_rot_convolution, tqdm_wav)
+                    )
+
+            else:  # num_procs == 0  or num_procs == 1
+                convolved_flux = np.empty_like(wavelength)  # Memory assignment
+                for ii, single_wav in enumerate(tqdm_wav):
+                    convolved_flux[ii] = element_rot_convolution(single_wav)
+        else:
+            try:
+                # Assume num_procs was a multiprocess.pool.Pool
                 convolved_flux = np.array(
-                    mproc_pool.map(element_rot_convolution, tqdm_wav)
+                    num_procs.map(element_rot_convolution, tqdm_wav)
                 )
-
-        else:  # num_procs == 0  or num_procs == 1
-            convolved_flux = np.empty_like(wavelength)  # Memory assignment
-            for ii, single_wav in enumerate(tqdm_wav):
-                convolved_flux[ii] = element_rot_convolution(single_wav)
-    else:
-        try:
-            # Assume num_procs was a multiprocess.pool.Pool
-            convolved_flux = np.array(num_procs.map(element_rot_convolution, tqdm_wav))
-        except AttributeError:
-            raise TypeError(
-                "num_proc must be an int or a multiprocess Pool. Not '{}'".format(
-                    type(num_procs)
+            except AttributeError:
+                raise TypeError(
+                    "num_proc must be an int or a multiprocess Pool. Not '{}'".format(
+                        type(num_procs)
+                    )
                 )
-            )
-
+    else:
+        # Skip convolution for vsini=0
+        if wavelength is extended_wav:
+            convolved_flux = extended_flux  # No change
+        else:
+            # Interpolate to the new wavelength vector.
+            convolved_flux = np.interp(wavelength, extended_wav, extended_flux)
     return convolved_flux
 
 


Test patch:
diff --git a/tests/test_broadening.py b/tests/test_broadening.py
index 2368a67..bd75ace 100644
--- a/tests/test_broadening.py
+++ b/tests/test_broadening.py
@@ -6,8 +6,8 @@ from multiprocess import Pool
 from eniric.broaden import (
     convolution,
     resolution_convolution,
-    rotational_convolution,
     rotation_kernel,
+    rotational_convolution,
     unitary_gaussian,
 )
 
@@ -165,3 +165,23 @@ def test_res_convolution_can_accept_None():
     x = np.linspace(2.0, 2.3, n)
     y = np.random.randn(n)
     resolution_convolution(x, x, y, R=100000, num_procs=None)
+
+
+@pytest.mark.parametrize("zero_vsini", [0, 0.00, np.int(0.0), np.float64(0.0)])
+def test_zero_rotation(zero_vsini):
+    n = 20
+    x = np.linspace(2.0, 2.3, n)
+    y = np.random.randn(n)
+    z = rotational_convolution(x, x, y, vsini=zero_vsini, num_procs=1)
+
+    assert np.all(y == z)
+
+
+@pytest.mark.parametrize("zero_vsini", [0, 0.00, np.int(0.0), np.float64(0.0)])
+def test_zero_rotation_with_different_x(zero_vsini):
+    n = 20
+    x = np.linspace(1000, 2300, n)
+    y = np.random.randn(n)
+    z = rotational_convolution(x[4:16], x, y, vsini=zero_vsini, num_procs=1)
+
+    assert np.all(y[4:16] == z)