Repository: paris-saclay-cds/specio

Issue:
Add an argument to read_csv to merge wavelength

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/paris-saclay-cds/specio/pull/44?src=pr&el=h1) Report
> Merging [#44](https://codecov.io/gh/paris-saclay-cds/specio/pull/44?src=pr&el=desc) into [master](https://codecov.io/gh/paris-saclay-cds/specio/commit/e966bc2b7f0955631517780272b8ebd62f6c6a1b?src=pr&el=desc) will **increase** coverage by `0.02%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/paris-saclay-cds/specio/pull/44/graphs/tree.svg?src=pr&token=IO4kafGqN0&height=150&width=650)](https://codecov.io/gh/paris-saclay-cds/specio/pull/44?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master      #44      +/-   ##
==========================================
+ Coverage   94.58%   94.61%   +0.02%     
==========================================
  Files          26       26              
  Lines        1219     1225       +6     
==========================================
+ Hits         1153     1159       +6     
  Misses         66       66
```


| [Impacted Files](https://codecov.io/gh/paris-saclay-cds/specio/pull/44?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [specio/core/functions.py](https://codecov.io/gh/paris-saclay-cds/specio/pull/44/diff?src=pr&el=tree#diff-c3BlY2lvL2NvcmUvZnVuY3Rpb25zLnB5) | `93.1% <100%> (+0.12%)` | :arrow_up: |
| [specio/core/tests/test\_functions.py](https://codecov.io/gh/paris-saclay-cds/specio/pull/44/diff?src=pr&el=tree#diff-c3BlY2lvL2NvcmUvdGVzdHMvdGVzdF9mdW5jdGlvbnMucHk=) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/paris-saclay-cds/specio/pull/44?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/paris-saclay-cds/specio/pull/44?src=pr&el=footer). Last update [e966bc2...9678af8](https://codecov.io/gh/paris-saclay-cds/specio/pull/44?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/specio/core/functions.py b/specio/core/functions.py
index c47f79d..8185e05 100644
--- a/specio/core/functions.py
+++ b/specio/core/functions.py
@@ -144,7 +144,7 @@ def _validate_filenames(uri):
         return sorted(glob.glob(os.path.expanduser(uri)))
 
 
-def _zip_spectrum(spectrum):
+def _zip_spectrum(spectrum, tol_wavelength):
     """Compress if possible several Spectrum into a single one.
 
     Parameters
@@ -152,6 +152,10 @@ def _zip_spectrum(spectrum):
     spectrum : list of Spectrum
         The list of Spectrum to zip.
 
+    tol_wavelength : float
+        Tolerance to merge spectrum when their wavelength are slightly
+        different.
+
     Returns
     -------
     zipped_spectrum : Spectrum or list of Spectrum
@@ -166,7 +170,8 @@ def _zip_spectrum(spectrum):
         wavelength = spectrum[0].wavelength
         try:
             consistent_wavelength = [np.allclose(sp.wavelength,
-                                                 wavelength)
+                                                 wavelength,
+                                                 atol=tol_wavelength)
                                      for sp in spectrum]
             if not all(consistent_wavelength):
                 return spectrum
@@ -194,7 +199,7 @@ def _zip_spectrum(spectrum):
         return output_spectrum
 
 
-def specread(uri, format=None, **kwargs):
+def specread(uri, format=None, tol_wavelength=1e-5, **kwargs):
     """Read spectra in a given format.
 
     Reads spectrum from the specified file. Returns a list or a
@@ -215,6 +220,10 @@ def specread(uri, format=None, **kwargs):
         The format to use to read the file. By default specio selects
         the appropriate for you based on the filename and its contents.
 
+    tol_wavelength : float, optional
+        Tolerance to merge spectrum when their wavelength are slightly
+        different.
+
     kwargs : dict
         Further keyword arguments are passed to the reader. See :func:`.help`
         to see what arguments are available for a particular format.
@@ -241,7 +250,7 @@ def specread(uri, format=None, **kwargs):
             spectrum = _get_reader_get_data(uri, format, **kwargs)
 
         if isinstance(spectrum, list):
-            spectrum = _zip_spectrum(spectrum)
+            spectrum = _zip_spectrum(spectrum, tol_wavelength)
 
         return spectrum
 


Test patch:
diff --git a/specio/core/tests/test_functions.py b/specio/core/tests/test_functions.py
index 0cfd489..049cdbb 100644
--- a/specio/core/tests/test_functions.py
+++ b/specio/core/tests/test_functions.py
@@ -87,14 +87,25 @@ def _generate_list_spectrum(*args):
             for _ in range(n_spectrum)]
 
 
+def _generate_list_spectrum_close_wavelength(*args):
+    n_wavelength = 5
+    tol = 1e-3
+    wavelength = np.arange(5) + np.random.uniform(low=-tol, high=tol)
+    return Spectrum(np.random.random(n_wavelength),
+                    wavelength,
+                    None)
+
+
 @pytest.mark.parametrize(
-    "side_effect,spectra_type,spectra_shape",
-    [(_generate_spectrum_identical_wavelength, Spectrum, (10, 5)),
-     (_generate_spectrum_different_wavelength_size, list, 10),
-     (_generate_spectrum_different_wavelength, list, 10),
-     (_generate_list_spectrum, list, 30)])
-def test_specread_consitent_wavelength(side_effect, spectra_type,
-                                       spectra_shape, mocker):
+    "side_effect,tol_wavelength,spectra_type,spectra_shape",
+    [(_generate_spectrum_identical_wavelength, 1e-5, Spectrum, (10, 5)),
+     (_generate_spectrum_different_wavelength_size, 1e-5, list, 10),
+     (_generate_spectrum_different_wavelength, 1e-5, list, 10),
+     (_generate_list_spectrum, 1e-5, list, 30),
+     (_generate_list_spectrum_close_wavelength, 1e-2, Spectrum, (10, 5)),
+     (_generate_list_spectrum_close_wavelength, 1e-5, list, 10)])
+def test_specread_consitent_wavelength(side_effect, tol_wavelength,
+                                       spectra_type, spectra_shape, mocker):
     # emulate that we read several file
     mocker.patch('specio.core.functions._validate_filenames',
                  return_value=['filename' for _ in range(10)])
@@ -103,7 +114,7 @@ def test_specread_consitent_wavelength(side_effect, spectra_type,
                  side_effect=side_effect)
 
     # emulate the spectrum reading
-    spectra = specread('')
+    spectra = specread('', tol_wavelength=tol_wavelength)
     assert isinstance(spectra, spectra_type)
     if isinstance(spectra, Spectrum):
         assert spectra.amplitudes.shape == spectra_shape