Repository: matchms/matchms
Pull request #477 (2023-08-11 14:17:19)

Complete filter order
Solves #476 

Added a test to check if ALL_FILTERS actually contains all the available filters.

The missing filters have been added and to helper functions (in the filter folders) a "_" has been added to the function name. 


Patch:
diff --git a/matchms/SpectrumProcessor.py b/matchms/SpectrumProcessor.py
index ca054596..2ed15fe4 100644
--- a/matchms/SpectrumProcessor.py
+++ b/matchms/SpectrumProcessor.py
@@ -198,17 +198,27 @@ ALL_FILTERS = [msfilters.make_charge_int,
                msfilters.harmonize_undefined_inchi,
                msfilters.harmonize_undefined_smiles,
                msfilters.repair_inchi_inchikey_smiles,
+               msfilters.derive_smiles_from_inchi,
+               msfilters.repair_smiles_from_compound_name,
+               msfilters.derive_inchi_from_smiles,
+               msfilters.derive_inchikey_from_inchi,
+               msfilters.clean_adduct,
+               msfilters.repair_smiles_of_salts,
+               msfilters.repair_precursor_is_parent_mass,
+               msfilters.repair_parent_mass_is_mol_wt,
+               msfilters.repair_adduct_based_on_smiles,
                msfilters.repair_parent_mass_match_smiles_wrapper,
                msfilters.require_correct_ionmode,
                msfilters.require_precursor_below_mz,
-               msfilters.require_parent_mass_match_smiles,
                msfilters.require_valid_annotation,
+               msfilters.require_parent_mass_match_smiles,
                msfilters.normalize_intensities,
                msfilters.select_by_intensity,
                msfilters.select_by_mz,
                msfilters.select_by_relative_intensity,
                msfilters.remove_peaks_around_precursor_mz,
                msfilters.remove_peaks_outside_top_k,
+               msfilters.reduce_to_number_of_peaks,
                msfilters.require_minimum_number_of_peaks,
                msfilters.require_minimum_of_high_peaks,
                msfilters.add_fingerprint,
@@ -240,8 +250,11 @@ DEFAULT_FILTERS = BASIC_FILTERS \
        "normalize_intensities",
     ]
 FULLY_ANNOTATED_PROCESSING = DEFAULT_FILTERS \
-    + [("require_correct_ionmode", {"ion_mode_to_keep": "both"}),
-       "require_parent_mass_match_smiles",
+    + ["clean_adduct",
+       "derive_inchi_from_smiles",
+       "derive_smiles_from_inchi",
+       ("require_correct_ionmode", {"ion_mode_to_keep": "both"}),
+       ("require_parent_mass_match_smiles", {'mass_tolerance': 0.1}),
        "require_valid_annotation",
     ]
 
diff --git a/matchms/filtering/filter_utils/derive_precursor_mz_and_parent_mass.py b/matchms/filtering/filter_utils/derive_precursor_mz_and_parent_mass.py
index f419277b..d673cc64 100644
--- a/matchms/filtering/filter_utils/derive_precursor_mz_and_parent_mass.py
+++ b/matchms/filtering/filter_utils/derive_precursor_mz_and_parent_mass.py
@@ -3,8 +3,9 @@ from typing import Optional, Tuple
 from matchms.constants import PROTON_MASS
 from matchms.filtering.filter_utils.interpret_unknown_adduct import \
     get_multiplier_and_mass_from_adduct
-from matchms.filtering.metadata_processing.clean_adduct import (
-    _clean_adduct, load_known_adducts)
+from matchms.filtering.filter_utils.load_known_adducts import \
+    load_known_adducts
+from matchms.filtering.metadata_processing.clean_adduct import _clean_adduct
 from matchms.typing import SpectrumType
 
 
diff --git a/matchms/filtering/filter_utils/load_known_adducts.py b/matchms/filtering/filter_utils/load_known_adducts.py
new file mode 100644
index 00000000..ef6fd661
--- /dev/null
+++ b/matchms/filtering/filter_utils/load_known_adducts.py
@@ -0,0 +1,44 @@
+import csv
+import os
+from functools import lru_cache
+from typing import Dict
+import pandas as pd
+
+
+@lru_cache(maxsize=4)
+def load_known_adducts() -> pd.DataFrame:
+    """Load dictionary of known adducts containing the adduct mass and charge.
+    Makes sure that file loading is cached.
+
+    Adduct information is based on information from
+    https://fiehnlab.ucdavis.edu/staff/kind/metabolomics/ms-adduct-calculator/
+    and was extended by F.Huber and JJJ.v.d.Hooft.
+
+    The full table can be found at
+    https://github.com/matchms/matchms/blob/expand_adducts/matchms/data/known_adducts_table.csv
+
+    """
+    known_adducts_file = os.path.join(os.path.dirname(__file__), "..", "..", "data", "known_adducts_table.csv")
+    assert os.path.isfile(known_adducts_file), "Could not find known_adducts_table.csv."
+
+    with open(known_adducts_file, newline='', encoding='utf-8-sig') as csvfile:
+        adducts_dataframe = pd.read_csv(csvfile)
+        assert list(adducts_dataframe.columns) == ["adduct", "ionmode", "charge", "mass_multiplier", "correction_mass"]
+    return adducts_dataframe
+
+
+@lru_cache(maxsize=4)
+def load_known_adduct_conversions() -> Dict[str, dict]:
+    """Load dictionary of known adduct conversions. Makes sure that file loading is cached.
+    """
+    adduct_conversions_file = os.path.join(os.path.dirname(__file__), "..", "..", "data",
+                                           "known_adduct_conversions.csv")
+    assert os.path.isfile(adduct_conversions_file), "Could not find known_adduct_conversions.csv."
+
+    with open(adduct_conversions_file, newline='', encoding='utf-8-sig') as csvfile:
+        reader = csv.DictReader(csvfile)
+        known_adduct_conversions = {}
+        for row in reader:
+            known_adduct_conversions[row['input_adduct']] = row['corrected_adduct']
+
+    return known_adduct_conversions
diff --git a/matchms/filtering/metadata_processing/add_retention.py b/matchms/filtering/metadata_processing/add_retention.py
index 8470ca49..b109a32a 100644
--- a/matchms/filtering/metadata_processing/add_retention.py
+++ b/matchms/filtering/metadata_processing/add_retention.py
@@ -13,7 +13,7 @@ _retention_time_keys = ["retention_time", "retentiontime", "rt", "scan_start_tim
 _retention_index_keys = ["retention_index", "retentionindex", "ri"]
 
 
-def safe_store_value(metadata: dict, value: Any, target_key: str) -> dict:
+def _safe_store_value(metadata: dict, value: Any, target_key: str) -> dict:
     """Helper function to safely store a value in the target key without throwing an exception, but storing 'None' instead.
 
     Parameters
@@ -30,12 +30,12 @@ def safe_store_value(metadata: dict, value: Any, target_key: str) -> dict:
     Spectrum with added key.
     """
     if value is not None:   # one of accepted keys is present
-        value = safe_convert_to_float(value)
+        value = _safe_convert_to_float(value)
     metadata[target_key] = value
     return metadata
 
 
-def safe_convert_to_float(value: Any) -> Optional[float]:
+def _safe_convert_to_float(value: Any) -> Optional[float]:
     """Safely convert value to float. Return 'None' on failure.
 
     Parameters
@@ -52,14 +52,14 @@ def safe_convert_to_float(value: Any) -> Optional[float]:
             value = value[0]
         else:
             return None
-        
+
     # logic to read MoNA msp files which specify rt as string with "min" in it
     if isinstance(value, str):
         value = value.strip()
         pattern = r'^[+-]?(\d*\.)?\d+\s*(min|s|h|ms)'
         conversion = {"min": 60, "s": 1, "h": 3600, "ms": 1e-3}
         match = re.search(pattern, value)
-        
+
         if match and len(match.groups()) == 2:
             val, unit = value.split(' ')
             return float(val) * conversion[unit]
@@ -90,10 +90,10 @@ def _add_retention(metadata: dict, target_key: str, accepted_keys: List[str]) ->
     """
     common_keys = get_common_keys(metadata.keys(), accepted_keys)
     values_for_keys = filter_none([metadata[key] for key in common_keys])
-    values = list(map(safe_convert_to_float, values_for_keys))
+    values = list(map(_safe_convert_to_float, values_for_keys))
     value = next(filter_none(values), None)
 
-    metadata = safe_store_value(metadata, value, target_key)
+    metadata = _safe_store_value(metadata, value, target_key)
     return metadata
 
 
diff --git a/matchms/filtering/metadata_processing/clean_adduct.py b/matchms/filtering/metadata_processing/clean_adduct.py
index 7460409d..982fb01a 100644
--- a/matchms/filtering/metadata_processing/clean_adduct.py
+++ b/matchms/filtering/metadata_processing/clean_adduct.py
@@ -1,10 +1,7 @@
-import csv
 import logging
-import os
 import re
-from functools import lru_cache
-from typing import Dict
-import pandas as pd
+from matchms.filtering.filter_utils.load_known_adducts import \
+    load_known_adduct_conversions
 
 
 logger = logging.getLogger("matchms")
@@ -40,14 +37,14 @@ def _clean_adduct(adduct: str) -> str:
     adduct
         Input adduct string to be cleaned/edited.
     """
-    def get_adduct_charge(adduct):
+    def _get_adduct_charge(adduct):
         regex_charges = r"[1-3]{0,1}[+-]{1,2}$"
         match = re.search(regex_charges, adduct)
         if match:
             return match.group(0)
         return match
 
-    def adduct_conversion(adduct):
+    def _adduct_conversion(adduct):
         """Convert adduct if conversion rule is known"""
         adduct_conversions = load_known_adduct_conversions()
         if adduct in adduct_conversions:
@@ -60,59 +57,20 @@ def _clean_adduct(adduct: str) -> str:
     adduct = adduct.strip().replace("\n", "").replace("*", "")
     adduct = adduct.replace("++", "2+").replace("--", "2-")
     if adduct.startswith("["):
-        return adduct_conversion(adduct)
+        return _adduct_conversion(adduct)
 
     if adduct.endswith("]"):
-        return adduct_conversion("[" + adduct)
+        return _adduct_conversion("[" + adduct)
 
     adduct_core = "[" + adduct
     # Remove parts that can confuse the charge extraction
     for mol_part in ["CH2", "CH3", "NH3", "NH4", "O2"]:
         if mol_part in adduct:
             adduct = adduct.split(mol_part)[-1]
-    adduct_charge = get_adduct_charge(adduct)
+    adduct_charge = _get_adduct_charge(adduct)
 
     if adduct_charge is None:
-        return adduct_conversion(adduct_core + "]")
+        return _adduct_conversion(adduct_core + "]")
 
     adduct_cleaned = adduct_core[:-len(adduct_charge)] + "]" + adduct_charge
-    return adduct_conversion(adduct_cleaned)
-
-
-@lru_cache(maxsize=4)
-def load_known_adducts() -> pd.DataFrame:
-    """Load dictionary of known adducts containing the adduct mass and charge.
-    Makes sure that file loading is cached.
-
-    Adduct information is based on information from
-    https://fiehnlab.ucdavis.edu/staff/kind/metabolomics/ms-adduct-calculator/
-    and was extended by F.Huber and JJJ.v.d.Hooft.
-
-    The full table can be found at
-    https://github.com/matchms/matchms/blob/expand_adducts/matchms/data/known_adducts_table.csv
-
-    """
-    known_adducts_file = os.path.join(os.path.dirname(__file__), "..", "..", "data", "known_adducts_table.csv")
-    assert os.path.isfile(known_adducts_file), "Could not find known_adducts_table.csv."
-
-    with open(known_adducts_file, newline='', encoding='utf-8-sig') as csvfile:
-        adducts_dataframe = pd.read_csv(csvfile)
-        assert list(adducts_dataframe.columns) == ["adduct", "ionmode", "charge", "mass_multiplier", "correction_mass"]
-    return adducts_dataframe
-
-
-@lru_cache(maxsize=4)
-def load_known_adduct_conversions() -> Dict[str, dict]:
-    """Load dictionary of known adduct conversions. Makes sure that file loading is cached.
-    """
-    adduct_conversions_file = os.path.join(os.path.dirname(__file__), "..", "..", "data",
-                                           "known_adduct_conversions.csv")
-    assert os.path.isfile(adduct_conversions_file), "Could not find known_adduct_conversions.csv."
-
-    with open(adduct_conversions_file, newline='', encoding='utf-8-sig') as csvfile:
-        reader = csv.DictReader(csvfile)
-        known_adduct_conversions = {}
-        for row in reader:
-            known_adduct_conversions[row['input_adduct']] = row['corrected_adduct']
-
-    return known_adduct_conversions
+    return _adduct_conversion(adduct_cleaned)
diff --git a/matchms/filtering/metadata_processing/clean_compound_name.py b/matchms/filtering/metadata_processing/clean_compound_name.py
index bb60e637..fdad83f0 100644
--- a/matchms/filtering/metadata_processing/clean_compound_name.py
+++ b/matchms/filtering/metadata_processing/clean_compound_name.py
@@ -12,50 +12,6 @@ def clean_compound_name(spectrum_in: SpectrumType) -> SpectrumType:
     A list of frequently seen name additions that do not belong to the compound
     name will be removed.
     """
-    def remove_parts_by_regular_expression(name):
-        """Clean name string by removing known parts that don't belong there."""
-        name = name.strip()
-        # remove type NCGC00180417-03_C31H40O16_
-        name = re.split(r"[A-Z]{3,6}[0-9]{8,12}-[0-9]{2,5}_[A-Z,0-9]{4,15}_", name)[-1]
-        # remove type NCGC00160232-01! or MLS001142816-01!
-        name = re.split(r"[A-Z]{3,6}[0-9]{8,12}-[0-9]{2,3}\!", name)[-1]
-        # remove type Massbank:EA008813 option1|option2|option3
-        name = re.split(r"((Massbank:)|(MassbankEU:))[A-Z]{2}[0-9]{5,6}.*\|", name)[-1]
-        # remove type Massbank:EA008813 or MassbankEU:EA008813
-        name = re.split(r"((Massbank:)|(MassbankEU:))[A-Z]{2}[0-9]{5,6}", name)[-1]
-        # remove type HMDB:HMDB00943-1336
-        name = re.split(r"HMDB:HMDB[0-9]{4,7}-[0-9]{1,7}", name)[-1]
-        # remove type MoNA:662599
-        name = re.split(r"MoNA:[0-9]{5,10}", name)[-1]
-        # ReSpect:PS013405 option1|option2|option3...
-        name = re.split(r"ReSpect:[A-Z]{2,3}[0-9]{6}.*\|", name)[-1]
-        # ReSpect:PS013405 option1
-        name = re.split(r"[A-Z]{2,3}[0-9]{6}( )", name)[-1]
-        # remove type 0072_2-Mercaptobenzothiaz
-        name = re.split(r"^[0-9]{4}_", name)[-1]
-        # remove type nameofcompound_CID20_170920 or Spiraeoside_HCD30_170919
-        name = re.split(r"_((HCD)|(CID))[0-9]{2}_[0-9]{5,6}$", name)[0]
-        # Removes the collision energy from the compound name. Also allows for occurances of - 40.0 eV Unknown
-        name = re.split(r"(?: - )?[0-9]+(?:\.[0-9]+)? ?[eE][Vv](?: Unknown)?$", name)[0]
-        return name
-
-    def remove_known_non_compound_parts(name):
-        """Remove known non compound-name strings from name."""
-        parts_remove = ["Spectral Match to",
-                        "from NIST14",
-                        "Massbank:"]
-        for part in parts_remove:
-            name = name.replace(part, "")
-        return name.strip("; ")
-
-    def remove_misplaced_mass(name):
-        """Remove occasionally occurring parent mass addition to name."""
-        regex_mass = r"^[0-9]{2,4}\.[0-9]$"
-        end_part = name.split(" ")[-1]
-        if re.search(regex_mass, end_part) is not None:
-            return name.replace(end_part, "").strip()
-        return name
-
     if spectrum_in is None:
         return None
 
@@ -69,11 +25,58 @@ def clean_compound_name(spectrum_in: SpectrumType) -> SpectrumType:
         return spectrum
 
     # Clean compound name
-    name_cleaned = remove_parts_by_regular_expression(name)
-    name_cleaned = remove_known_non_compound_parts(name_cleaned)
-    name_cleaned = remove_misplaced_mass(name_cleaned)
+    name_cleaned = _remove_parts_by_regular_expression(name)
+    name_cleaned = _remove_known_non_compound_parts(name_cleaned)
+    name_cleaned = _remove_misplaced_mass(name_cleaned)
     if name_cleaned != name:
         spectrum.set("compound_name", name_cleaned)
         logger.info("Added cleaned compound name: %s", name_cleaned)
 
     return spectrum
+
+
+def _remove_parts_by_regular_expression(name):
+    """Clean name string by removing known parts that don't belong there."""
+    name = name.strip()
+    # remove type NCGC00180417-03_C31H40O16_
+    name = re.split(r"[A-Z]{3,6}[0-9]{8,12}-[0-9]{2,5}_[A-Z,0-9]{4,15}_", name)[-1]
+    # remove type NCGC00160232-01! or MLS001142816-01!
+    name = re.split(r"[A-Z]{3,6}[0-9]{8,12}-[0-9]{2,3}\!", name)[-1]
+    # remove type Massbank:EA008813 option1|option2|option3
+    name = re.split(r"((Massbank:)|(MassbankEU:))[A-Z]{2}[0-9]{5,6}.*\|", name)[-1]
+    # remove type Massbank:EA008813 or MassbankEU:EA008813
+    name = re.split(r"((Massbank:)|(MassbankEU:))[A-Z]{2}[0-9]{5,6}", name)[-1]
+    # remove type HMDB:HMDB00943-1336
+    name = re.split(r"HMDB:HMDB[0-9]{4,7}-[0-9]{1,7}", name)[-1]
+    # remove type MoNA:662599
+    name = re.split(r"MoNA:[0-9]{5,10}", name)[-1]
+    # ReSpect:PS013405 option1|option2|option3...
+    name = re.split(r"ReSpect:[A-Z]{2,3}[0-9]{6}.*\|", name)[-1]
+    # ReSpect:PS013405 option1
+    name = re.split(r"[A-Z]{2,3}[0-9]{6}( )", name)[-1]
+    # remove type 0072_2-Mercaptobenzothiaz
+    name = re.split(r"^[0-9]{4}_", name)[-1]
+    # remove type nameofcompound_CID20_170920 or Spiraeoside_HCD30_170919
+    name = re.split(r"_((HCD)|(CID))[0-9]{2}_[0-9]{5,6}$", name)[0]
+    # Removes the collision energy from the compound name. Also allows for occurances of - 40.0 eV Unknown
+    name = re.split(r"(?: - )?[0-9]+(?:\.[0-9]+)? ?[eE][Vv](?: Unknown)?$", name)[0]
+    return name
+
+
+def _remove_known_non_compound_parts(name):
+    """Remove known non compound-name strings from name."""
+    parts_remove = ["Spectral Match to",
+                    "from NIST14",
+                    "Massbank:"]
+    for part in parts_remove:
+        name = name.replace(part, "")
+    return name.strip("; ")
+
+
+def _remove_misplaced_mass(name):
+    """Remove occasionally occurring parent mass addition to name."""
+    regex_mass = r"^[0-9]{2,4}\.[0-9]$"
+    end_part = name.split(" ")[-1]
+    if re.search(regex_mass, end_part) is not None:
+        return name.replace(end_part, "").strip()
+    return name
diff --git a/matchms/filtering/metadata_processing/derive_adduct_from_name.py b/matchms/filtering/metadata_processing/derive_adduct_from_name.py
index a365c1fc..8eea01a5 100644
--- a/matchms/filtering/metadata_processing/derive_adduct_from_name.py
+++ b/matchms/filtering/metadata_processing/derive_adduct_from_name.py
@@ -1,7 +1,8 @@
 import logging
 import re
 from matchms.typing import SpectrumType
-from .clean_adduct import _clean_adduct, load_known_adducts
+from ..filter_utils.load_known_adducts import load_known_adducts
+from .clean_adduct import _clean_adduct
 
 
 logger = logging.getLogger("matchms")
@@ -36,7 +37,7 @@ def derive_adduct_from_name(spectrum_in: SpectrumType,
     adduct_from_name = None
     name_split = name.split(" ")
     for name_part in name_split[::-1][:2]:
-        if looks_like_adduct(name_part):
+        if _looks_like_adduct(name_part):
             adduct_from_name = name_part
             break
 
@@ -47,7 +48,7 @@ def derive_adduct_from_name(spectrum_in: SpectrumType,
         logger.info("Removed adduct %s from compound name.", adduct_from_name)
 
     # Add found adduct to metadata (if not present yet)
-    if adduct_from_name and not looks_like_adduct(spectrum.get("adduct")):
+    if adduct_from_name and not _looks_like_adduct(spectrum.get("adduct")):
         adduct_cleaned = _clean_adduct(adduct_from_name)
         spectrum.set("adduct", adduct_cleaned)
         logger.info("Added adduct %s from the compound name to metadata.", spectrum.get('adduct'))
@@ -55,7 +56,7 @@ def derive_adduct_from_name(spectrum_in: SpectrumType,
     return spectrum
 
 
-def looks_like_adduct(adduct):
+def _looks_like_adduct(adduct):
     """Return True if input string has expected format of an adduct."""
     if not isinstance(adduct, str):
         return False
diff --git a/matchms/filtering/metadata_processing/derive_formula_from_name.py b/matchms/filtering/metadata_processing/derive_formula_from_name.py
index 49c66b8f..4e10d69b 100644
--- a/matchms/filtering/metadata_processing/derive_formula_from_name.py
+++ b/matchms/filtering/metadata_processing/derive_formula_from_name.py
@@ -35,7 +35,7 @@ def derive_formula_from_name(spectrum_in: SpectrumType,
 
     # Detect formula at end of compound name
     end_of_name = name.split(" ")[-1]
-    formula_from_name = end_of_name if looks_like_formula(end_of_name) else None
+    formula_from_name = end_of_name if _looks_like_formula(end_of_name) else None
 
     if formula_from_name and remove_formula_from_name:
         name_formula_removed = " ".join(name.split(" ")[:-1])
@@ -50,7 +50,7 @@ def derive_formula_from_name(spectrum_in: SpectrumType,
     return spectrum
 
 
-def looks_like_formula(formula):
+def _looks_like_formula(formula):
     """Return True if input string has expected format of a molecular formula.
     Does only consider most frequent atoms found in many name strings.
     """
diff --git a/matchms/filtering/metadata_processing/derive_ionmode.py b/matchms/filtering/metadata_processing/derive_ionmode.py
index e4fe76bc..11bb15a1 100644
--- a/matchms/filtering/metadata_processing/derive_ionmode.py
+++ b/matchms/filtering/metadata_processing/derive_ionmode.py
@@ -1,6 +1,7 @@
 import logging
 from matchms.typing import SpectrumType
-from .clean_adduct import _clean_adduct, load_known_adducts
+from ..filter_utils.load_known_adducts import load_known_adducts
+from .clean_adduct import _clean_adduct
 
 
 logger = logging.getLogger("matchms")
diff --git a/matchms/filtering/metadata_processing/make_charge_int.py b/matchms/filtering/metadata_processing/make_charge_int.py
index 2c888406..90a75efc 100644
--- a/matchms/filtering/metadata_processing/make_charge_int.py
+++ b/matchms/filtering/metadata_processing/make_charge_int.py
@@ -22,7 +22,7 @@ def make_charge_int(spectrum_in: SpectrumType) -> SpectrumType:
 
 def _convert_charge_to_int(charge):
     """Convert charge to integer if possible, else return None."""
-    def try_conversion(charge):
+    def _try_conversion(charge):
         try:
             return int(charge)
         except ValueError:
@@ -38,11 +38,11 @@ def _convert_charge_to_int(charge):
 
     # Avoid pyteomics ChargeList
     if isinstance(charge, list):
-        return try_conversion(charge[0])
+        return _try_conversion(charge[0])
 
     # convert string charges to int
     if isinstance(charge, str):
         charge = charge.strip().replace("+", "")
         if len(charge) > 1 and charge[-1] == "-":
             charge = "-" + charge.replace("-", "")
-        return try_conversion(charge)
+        return _try_conversion(charge)
diff --git a/matchms/filtering/metadata_processing/repair_adduct_based_on_smiles.py b/matchms/filtering/metadata_processing/repair_adduct_based_on_smiles.py
index 02ee445c..b577997a 100644
--- a/matchms/filtering/metadata_processing/repair_adduct_based_on_smiles.py
+++ b/matchms/filtering/metadata_processing/repair_adduct_based_on_smiles.py
@@ -2,8 +2,7 @@ import logging
 from matchms import Spectrum
 from matchms.filtering.filter_utils.get_neutral_mass_from_smiles import \
     get_monoisotopic_neutral_mass
-from matchms.filtering.metadata_processing.clean_adduct import \
-    load_known_adducts
+from ..filter_utils.load_known_adducts import load_known_adducts
 from .repair_parent_mass_is_mol_wt import repair_parent_mass_is_mol_wt
 
 
diff --git a/matchms/filtering/metadata_processing/repair_smiles_from_compound_name.py b/matchms/filtering/metadata_processing/repair_smiles_from_compound_name.py
index 78b58189..451a4889 100644
--- a/matchms/filtering/metadata_processing/repair_smiles_from_compound_name.py
+++ b/matchms/filtering/metadata_processing/repair_smiles_from_compound_name.py
@@ -26,20 +26,20 @@ def repair_smiles_from_compound_name(spectrum_in: Spectrum,
         The input spectrum.
     annotated_compound_names_file: str
         A csv file containing the compound names and matching smiles, inchi, inchikey
-        and monoisotopic_mass.
+        and monoisotopic_mass. This can be created using the the pubchem_lookup.py from matchmextras.
     mass_tolerance.
         Acceptable mass difference between query compound and pubchem result.
     """
-    annotated_compound_names = load_compond_name_annotations(annotated_compound_names_file)
+    annotated_compound_names = _load_compound_name_annotations(annotated_compound_names_file)
     if spectrum_in is None:
         return None
     spectrum = spectrum_in.clone()
-    if check_fully_annotated(spectrum):
+    if _check_fully_annotated(spectrum):
         return spectrum
     compound_name = spectrum.get("compound_name")
     parent_mass = spectrum.get('parent_mass')
 
-    if is_plausible_name(compound_name) and parent_mass is not None:
+    if _is_plausible_name(compound_name) and parent_mass is not None:
         matching_compound_name = annotated_compound_names[annotated_compound_names["compound_name"] == compound_name]
         mass_differences = np.abs(matching_compound_name["monoisotopic_mass"]-parent_mass)
         within_mass_tolerance = matching_compound_name[mass_differences < mass_tolerance]
@@ -54,7 +54,7 @@ def repair_smiles_from_compound_name(spectrum_in: Spectrum,
     return spectrum
 
 
-def load_compond_name_annotations(annotated_compound_names_file):
+def _load_compound_name_annotations(annotated_compound_names_file):
     """Loads in the annotated compound names and checks format"""
     annotated_compound_names = pd.read_csv(annotated_compound_names_file)
     assert list(annotated_compound_names.columns) == ["compound_name", "smiles", "inchi",
@@ -63,7 +63,7 @@ def load_compond_name_annotations(annotated_compound_names_file):
     return annotated_compound_names
 
 
-def check_fully_annotated(spectrum: Spectrum) -> bool:
+def _check_fully_annotated(spectrum: Spectrum) -> bool:
     """Combine multiple check functions.
     Returns False if SMILES, InChIKey, or InChI are missing.
     """
@@ -76,6 +76,6 @@ def check_fully_annotated(spectrum: Spectrum) -> bool:
     return True
 
 
-def is_plausible_name(compound_name):
+def _is_plausible_name(compound_name):
     """Simple check if it can be a compound name."""
     return isinstance(compound_name, str) and len(compound_name) > 4
diff --git a/matchms/filtering/metadata_processing/repair_smiles_of_salts.py b/matchms/filtering/metadata_processing/repair_smiles_of_salts.py
index fd2ef73b..7f31c8f0 100644
--- a/matchms/filtering/metadata_processing/repair_smiles_of_salts.py
+++ b/matchms/filtering/metadata_processing/repair_smiles_of_salts.py
@@ -18,7 +18,7 @@ def repair_smiles_of_salts(spectrum_in,
 
     smiles = spectrum.get("smiles")
     parent_mass = spectrum.get("parent_mass")
-    possible_ion_combinations = create_possible_ions(smiles)
+    possible_ion_combinations = _create_possible_ions(smiles)
     if not possible_ion_combinations:
         # It is not a salt
         return spectrum
@@ -38,7 +38,7 @@ def repair_smiles_of_salts(spectrum_in,
     return spectrum
 
 
-def create_possible_ions(smiles):
+def _create_possible_ions(smiles):
     """Selects all possible ion combinations of a salt"""
 
     results = []
diff --git a/matchms/filtering/metadata_processing/require_valid_annotation.py b/matchms/filtering/metadata_processing/require_valid_annotation.py
index 4e3eeb6e..39be1489 100644
--- a/matchms/filtering/metadata_processing/require_valid_annotation.py
+++ b/matchms/filtering/metadata_processing/require_valid_annotation.py
@@ -24,12 +24,12 @@ def require_valid_annotation(spectrum: Spectrum):
     if not is_valid_inchi(inchi):
         logger.info("Removed spectrum since inchi is not valid. Incorrect inchi = %s", inchi)
         return None
-    if not check_smiles_inchi_inchikey_match(spectrum):
+    if not _check_smiles_inchi_inchikey_match(spectrum):
         return None
     return spectrum
 
 
-def check_smiles_inchi_inchikey_match(spectrum) -> bool:
+def _check_smiles_inchi_inchikey_match(spectrum) -> bool:
     """Checks if a spectrum"""
     if spectrum is None:
         return False


Test patch:
diff --git a/tests/filtering/test_derive_adduct_from_name.py b/tests/filtering/test_derive_adduct_from_name.py
index 72bb13f7..8b8ce5a0 100644
--- a/tests/filtering/test_derive_adduct_from_name.py
+++ b/tests/filtering/test_derive_adduct_from_name.py
@@ -2,7 +2,7 @@ import pytest
 from testfixtures import LogCapture
 from matchms.filtering import derive_adduct_from_name
 from matchms.filtering.metadata_processing.derive_adduct_from_name import \
-    looks_like_adduct
+    _looks_like_adduct
 from matchms.logging_functions import (reset_matchms_logger,
                                        set_matchms_logger_level)
 from ..builder_Spectrum import SpectrumBuilder
@@ -47,6 +47,6 @@ def test_looks_like_adduct():
     """Test if adducts are correctly identified"""
     for adduct in ["M+", "M*+", "M+Cl", "[M+H]", "[2M+Na]+", "M+H+K", "[2M+ACN+H]+",
                    "MS+Na", "MS+H", "M3Cl37+Na", "[M+H+H2O]"]:
-        assert looks_like_adduct(adduct), "Expected this to be identified as adduct"
+        assert _looks_like_adduct(adduct), "Expected this to be identified as adduct"
     for adduct in ["N+", "B*+", "++", "--", "[--]", "H+M+K"]:
-        assert not looks_like_adduct(adduct), "Expected this not to be identified as adduct"
+        assert not _looks_like_adduct(adduct), "Expected this not to be identified as adduct"
diff --git a/tests/filtering/test_filter_utils/test_interpret_unknown_adduct.py b/tests/filtering/test_filter_utils/test_interpret_unknown_adduct.py
index 0a7c53d6..4fa8c34e 100644
--- a/tests/filtering/test_filter_utils/test_interpret_unknown_adduct.py
+++ b/tests/filtering/test_filter_utils/test_interpret_unknown_adduct.py
@@ -1,7 +1,7 @@
 import pytest
 from matchms.filtering.filter_utils.interpret_unknown_adduct import \
     get_multiplier_and_mass_from_adduct
-from matchms.filtering.metadata_processing.clean_adduct import \
+from matchms.filtering.filter_utils.load_known_adducts import \
     load_known_adducts
 
 
diff --git a/tests/filtering/test_load_adducts.py b/tests/filtering/test_load_adducts.py
index 8fe7414b..4c77c229 100644
--- a/tests/filtering/test_load_adducts.py
+++ b/tests/filtering/test_load_adducts.py
@@ -1,6 +1,6 @@
 import numpy as np
 import pandas as pd
-from matchms.filtering.metadata_processing.clean_adduct import (
+from matchms.filtering.filter_utils.load_known_adducts import (
     load_known_adduct_conversions, load_known_adducts)
 
 
diff --git a/tests/filtering/test_spectrum_processor.py b/tests/filtering/test_spectrum_processor.py
index 849839c2..0cad682c 100644
--- a/tests/filtering/test_spectrum_processor.py
+++ b/tests/filtering/test_spectrum_processor.py
@@ -1,7 +1,9 @@
+import ast
+import os
 import numpy as np
 import pytest
 from matchms import SpectrumProcessor
-from matchms.SpectrumProcessor import ProcessingReport
+from matchms.SpectrumProcessor import ALL_FILTERS, ProcessingReport
 from ..builder_Spectrum import SpectrumBuilder
 
 
@@ -178,3 +180,49 @@ def test_add_filter_with_matchms_filter(spectrums):
     assert filters[-1].__name__ == "require_correct_ionmode"
     spectrums, _ = processor.process_spectrums(spectrums, create_report=True)
     assert not spectrums, "Expected to be empty list"
+
+
+def test_all_filters_is_complete():
+    """Checks that the global varible ALL_FILTERS contains all the available filters
+
+    This is important, since performing tests in the wrong order can make some filters useless.
+    """
+    def get_functions_from_file(file_path):
+        """Gets all python functions in a file"""
+        with open(file_path, 'r', encoding="utf-8") as file:
+            tree = ast.parse(file.read(), filename=file_path)
+        functions = []
+        for node in ast.walk(tree):
+            if isinstance(node, ast.FunctionDef):
+                functions.append(node.name)
+        return functions
+
+    current_dir = os.path.dirname(os.path.abspath(__file__))
+    filtering_directory = os.path.join(current_dir, "../../matchms/filtering")
+    directories_with_filters = ["metadata_processing",
+                                "peak_processing"]
+
+    all_filters = [filter.__name__ for filter in ALL_FILTERS]
+    list_of_filter_function_names = []
+    for directory_with_filters in directories_with_filters:
+        directory_with_filters = os.path.join(filtering_directory, directory_with_filters)
+        scripts = os.listdir(directory_with_filters)
+        for script in scripts:
+            # Remove __init__
+            if script[0] == "_":
+                break
+            if script[-3:] == ".py":
+                functions = get_functions_from_file(os.path.join(directory_with_filters, script))
+                for function in functions:
+                    if function[0] != "_":
+                        list_of_filter_function_names.append((script, function))
+    for script, filter_function in list_of_filter_function_names:
+        assert filter_function in all_filters, \
+            f"The function {filter_function} in the script {script} is not given in ALL_FILTERS, " \
+            f"this should be added to ensure a correct order of filter functions." \
+            f"If this function is not a filter add a _ before the function name"
+
+
+def test_all_filters_no_duplicates():
+    all_filters = [filter.__name__ for filter in ALL_FILTERS]
+    assert len(all_filters) == len(set(all_filters)), "One of the filters appears twice in ALL_FILTERS"