Repository: matchms/matchms
Pull request #396 (2023-04-12 08:52:42)

Load all file types
Added a function to infer filetype when loading in functions. 

For most other tools using Matchms a function is needed that just uses the extension to assume file type. This has now been added. 

@florian-huber @hechth Do you agree with this implementation? 


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f9f78501..25c00c74 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ## [Unreleased]
 
 ### Added
+- Added function to infer filetype when loading spectra
 
 ### Changed
 
diff --git a/matchms/importing/__init__.py b/matchms/importing/__init__.py
index de18f101..f18921d1 100644
--- a/matchms/importing/__init__.py
+++ b/matchms/importing/__init__.py
@@ -21,6 +21,7 @@ from .load_from_mzml import load_from_mzml
 from .load_from_mzxml import load_from_mzxml
 from .load_from_usi import load_from_usi
 from .load_scores import scores_from_json, scores_from_pickle
+from .load_spectra import load_from_pickle, load_spectra
 
 
 __all__ = [
@@ -30,6 +31,8 @@ __all__ = [
     "load_from_mzml",
     "load_from_mzxml",
     "load_from_usi",
+    "load_spectra",
+    "load_from_pickle",
     "scores_from_json",
     "scores_from_pickle",
 ]
diff --git a/matchms/importing/load_spectra.py b/matchms/importing/load_spectra.py
new file mode 100644
index 00000000..a58ad4d7
--- /dev/null
+++ b/matchms/importing/load_spectra.py
@@ -0,0 +1,60 @@
+import os
+import pickle
+from typing import Any, Generator, Optional
+from matchms.importing import (load_from_json, load_from_mgf, load_from_msp,
+                               load_from_mzml, load_from_mzxml, load_from_usi)
+from matchms.typing import SpectrumType
+
+
+def load_spectra(file: str, ftype: Optional[str] = None) -> Generator[SpectrumType, None, None]:
+    """Loads spectra from your spectrum file into memory as matchms Spectrum object
+
+    The following file extensions can be loaded in with this function:
+    "mzML", "json", "mgf", "msp", "mzxml", "usi" and "pickle".
+    A pickled file is expected to directly contain a list of matchms spectrum objects.
+
+    Args:
+    -----
+    file:
+        Path to file containing spectra, with file extension "mzML", "json", "mgf", "msp",
+        "mzxml", "usi" or "pickle"
+    ftype:
+        Optional. Filetype
+    """
+    assert os.path.exists(file), f"The specified file: {file} does not exists"
+
+    if ftype is None:
+        ftype = os.path.splitext(file)[1].lower()[1:]
+
+    if ftype == "mzml":
+        return load_from_mzml(file)
+    if ftype == "json":
+        return load_from_json(file)
+    if ftype == "mgf":
+        return load_from_mgf(file)
+    if ftype == "msp":
+        return load_from_msp(file)
+    if ftype == "mzxml":
+        return load_from_mzxml(file)
+    if ftype == "usi":
+        return load_from_usi(file)
+    if ftype == "pickle":
+        spectra = load_from_pickle(file)
+        assert isinstance(spectra, list), "Expected list of spectra"
+        assert isinstance(spectra[0], SpectrumType), "Expected list of spectra"
+        return spectra
+    assert False, f"File extension of file: {file} is not recognized"
+
+
+def load_from_pickle(filename: str) -> Any:
+    """Load spectra stored in pickle
+
+    Args:
+        filename (str): Pickled file with spectra.
+
+    Returns:
+        Any: Unpickled object. Should be a list of Spectra.
+    """
+    with open(filename, 'rb') as file:
+        loaded_object = pickle.load(file)
+    return loaded_object


Test patch:
diff --git a/tests/test_load_spectra.py b/tests/test_load_spectra.py
new file mode 100644
index 00000000..cbb7d2d1
--- /dev/null
+++ b/tests/test_load_spectra.py
@@ -0,0 +1,30 @@
+import os
+import pytest
+from matchms import Spectrum
+from matchms.importing.load_spectra import load_spectra
+
+
+def test_load_spectra_unknown_file(tmp_path):
+    """Tests if unknown file raises an Assertion error"""
+    with pytest.raises(AssertionError):
+        load_spectra(os.path.join(tmp_path, "file_that_does_not_exist.json"))
+
+
+@pytest.mark.parametrize("filename, ftype, expected_num_spectra", [
+    ["pesticides.mgf", None, 76],
+    ["testdata.mgf", "mgf", 30],
+    ["testdata.mzml", None, 10],
+    ["testdata.mzXML", None, 1],
+    ["massbank_five_spectra.msp", None, 5]
+])
+def test_load_spectra(filename, ftype, expected_num_spectra):
+    """Test if pickled file is loaded in correctly"""
+    tests_root = os.path.join(os.path.dirname(__file__), "../tests")
+    file = os.path.join(tests_root, filename)
+    actual = list(load_spectra(file, ftype=ftype))
+   
+        
+    assert isinstance(actual, list), "expected list of spectra"
+    assert len(actual) == expected_num_spectra
+    for spectrum in actual:
+        assert isinstance(spectrum, Spectrum)