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).

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
 

Add an argument to read_csv to merge wavelength
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

pip install -e .[tests,docs]
parse_log_pytest
requirements.txt
pytest pytest-cov pytest-mock sphinx sphinx-gallery sphinx_rtd_theme numpydoc matplotlib
apt-get update apt-get install -y gcc
3.6
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.13
attrs==22.2.0
Babel==2.11.0
certifi==2021.5.30
charset-normalizer==2.0.12
coverage==6.2
cycler==0.11.0
docutils==0.18.1
idna==3.10
imagesize==1.4.1
importlib-metadata==4.8.3
iniconfig==1.1.1
Jinja2==3.0.3
kiwisolver==1.3.1
MarkupSafe==2.0.1
matplotlib==3.3.4
numpy==1.19.5
numpydoc==1.1.0
packaging==21.3
Pillow==8.4.0
pluggy==1.0.0
py==1.11.0
Pygments==2.14.0
pyopenms==2.6.0
pyparsing==3.1.4
pytest==7.0.1
pytest-cov==4.0.0
pytest-mock==3.6.1
python-dateutil==2.9.0.post0
pytz==2025.2
requests==2.27.1
six==1.17.0
snowballstemmer==2.2.0
spc @ git+https://github.com/glemaitre/spc.git@44b67d49e1e4fe9364e7cbce9a93086037703511
-e git+https://github.com/paris-saclay-cds/specio.git@e966bc2b7f0955631517780272b8ebd62f6c6a1b#egg=specio
Sphinx==5.3.0
sphinx-gallery==0.10.0
sphinx-rtd-theme==2.0.0
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jquery==4.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
tomli==1.2.3
typing_extensions==4.1.1
urllib3==1.26.20
zipp==3.6.0

name: specio
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.13
      - attrs==22.2.0
      - babel==2.11.0
      - charset-normalizer==2.0.12
      - coverage==6.2
      - cycler==0.11.0
      - docutils==0.18.1
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - jinja2==3.0.3
      - kiwisolver==1.3.1
      - markupsafe==2.0.1
      - matplotlib==3.3.4
      - numpy==1.19.5
      - numpydoc==1.1.0
      - packaging==21.3
      - pillow==8.4.0
      - pluggy==1.0.0
      - py==1.11.0
      - pygments==2.14.0
      - pyopenms==2.6.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - pytest-cov==4.0.0
      - pytest-mock==3.6.1
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - requests==2.27.1
      - six==1.17.0
      - snowballstemmer==2.2.0
      - spc==0.4.0
      - sphinx==5.3.0
      - sphinx-gallery==0.10.0
      - sphinx-rtd-theme==2.0.0
      - sphinxcontrib-applehelp==1.0.2
      - sphinxcontrib-devhelp==1.0.2
      - sphinxcontrib-htmlhelp==2.0.0
      - sphinxcontrib-jquery==4.1
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==1.0.3
      - sphinxcontrib-serializinghtml==1.1.5
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - urllib3==1.26.20
      - zipp==3.6.0
prefix: /opt/conda/envs/specio

specio/core/tests/test_functions.py::test_specread_consitent_wavelength[_generate_spectrum_identical_wavelength-1e-05-Spectrum-spectra_shape0] specio/core/tests/test_functions.py::test_specread_consitent_wavelength[_generate_spectrum_different_wavelength_size-1e-05-list-10] specio/core/tests/test_functions.py::test_specread_consitent_wavelength[_generate_spectrum_different_wavelength-1e-05-list-10] specio/core/tests/test_functions.py::test_specread_consitent_wavelength[_generate_list_spectrum-1e-05-list-30] specio/core/tests/test_functions.py::test_specread_consitent_wavelength[_generate_list_spectrum_close_wavelength-0.01-Spectrum-spectra_shape4] specio/core/tests/test_functions.py::test_specread_consitent_wavelength[_generate_list_spectrum_close_wavelength-1e-05-list-10]
specio/core/tests/test_functions.py::test_get_reader_error[ValueError-Could specio/core/tests/test_functions.py::test_get_reader_error[OSError-No specio/core/tests/test_functions.py::test_get_reader_error[IndexError-No
specio/core/tests/test_functions.py::test_help specio/core/tests/test_functions.py::test_get_reader specio/core/tests/test_functions.py::test_specread_single_file
specio/core/functions.py
specio/core/functions.py