Repository: bedapub/besca (language: python)

Issue:
Allow a '-' in gene names
Currently you get a warning about when importing csv files containing gene names like "HLA-DOB"


Discussion / hints:

Fix patch:
diff --git a/besca/Import/_read.py b/besca/Import/_read.py
index 47ab7b64..43890686 100644
--- a/besca/Import/_read.py
+++ b/besca/Import/_read.py
@@ -2,6 +2,7 @@
 import sys
 import re
 import warnings
+
 warnings.simplefilter("default")
 from typing import List
 
@@ -193,17 +194,17 @@ def read_mtx(
             adata.var["SYMBOL"] = symbols.tolist()
         else:
             # lookup the corresponding Symbols
-            adata.var["SYMBOL"] = convert_ensembl_to_symbol(
-                ensembl_id, species=species
-            )
+            adata.var["SYMBOL"] = convert_ensembl_to_symbol(ensembl_id, species=species)
     else:
         sys.exit("Supplied unknown 'use_genes' parameter")
 
     check_response = check_data_for_citeseq(var_anno=var_anno)
 
-    if citeseq == 'gex_only' or citeseq == 'citeseq_only':
+    if citeseq == "gex_only" or citeseq == "citeseq_only":
         if check_response is False:
-            raise ValueError("'genes.tsv' does not include citeseq data or 'genes.tsv' has invalid citeseq values.")
+            raise ValueError(
+                "'genes.tsv' does not include citeseq data or 'genes.tsv' has invalid citeseq values."
+            )
         features = var_anno[2]
         adata.var["feature_type"] = features.tolist()
 
@@ -214,13 +215,19 @@ def read_mtx(
             adata = adata[:, adata.var.feature_type == "Antibody Capture"].copy()
     elif citeseq is None:
         if check_response is True:
-            warnings.warn("Citeseq data has been detected!, if you want to use it, please change citeseq parameter. Besca will continue without using the citeseq data")
+            warnings.warn(
+                "Citeseq data has been detected!, if you want to use it, please change citeseq parameter. Besca will continue without using the citeseq data"
+            )
     elif type(citeseq) == type(True) and citeseq is False:
-            if check_response is False:
-                warnings.warn("Citeseq data does not exists or is invalid!, change citeseq parameter to 'None' if there is no citeseq data existing!")
+        if check_response is False:
+            warnings.warn(
+                "Citeseq data does not exists or is invalid!, change citeseq parameter to 'None' if there is no citeseq data existing!"
+            )
     else:
-        raise ValueError("citeseq parameters has invalid value. Possible values: 'gex_only', 'citeseq_only', False or None.")
-    
+        raise ValueError(
+            "citeseq parameters has invalid value. Possible values: 'gex_only', 'citeseq_only', False or None."
+        )
+
     if annotation:
         print("adding annotation")
         adata.obs = pd.read_csv(
@@ -260,9 +267,11 @@ def all_ensembl_codes_ok(ensembl_id_list: List[str]) -> bool:
     """
 
     ensembl_regexp = re.compile(r"ENS[A-Z]+[0-9]{11}")
-    faulty_ensembl_genes = [gene for gene in ensembl_id_list if not ensembl_regexp.fullmatch(gene)]
+    faulty_ensembl_genes = [
+        gene for gene in ensembl_id_list if not ensembl_regexp.fullmatch(gene)
+    ]
 
-    if (faulty_ensembl_genes):
+    if faulty_ensembl_genes:
         warnings.warn(f"Detected faulty ENSEMBL gene names: {faulty_ensembl_genes}")
         return False
 
@@ -292,10 +301,14 @@ def all_symbols_ok(symbols_list: List[str]) -> bool:
         False
     """
 
-    symbol_regexp = re.compile(r"(?!\.)(?!NA$|na$|Na$|nA$)(?=.*[a-zA-Z].*)([a-zA-Z0-9\.]+)")
-    faulty_symbol_genes = [gene for gene in symbols_list if not symbol_regexp.fullmatch(gene)]
+    symbol_regexp = re.compile(
+        r"(?!\.)(?!NA$|na$|Na$|nA$)(?=.*[a-zA-Z].*)([a-zA-Z0-9\.\-]+)"
+    )
+    faulty_symbol_genes = [
+        gene for gene in symbols_list if not symbol_regexp.fullmatch(gene)
+    ]
 
-    if (faulty_symbol_genes):
+    if faulty_symbol_genes:
         warnings.warn(f"Detected faulty symbol gene names: {faulty_symbol_genes}")
         return False
 
@@ -314,12 +327,13 @@ def check_data_for_citeseq(var_anno):
     """
     if (len(var_anno.columns)) >= 3:
         values = var_anno.iloc[:, 2].unique()
-        if set(values) == set(['Gene Expression']) or \
-            set(values) == set(['Antibody Capture']) or \
-            set(values) == set(['Antibody Capture', 'Gene Expression']):
+        if (
+            set(values) == set(["Gene Expression"])
+            or set(values) == set(["Antibody Capture"])
+            or set(values) == set(["Antibody Capture", "Gene Expression"])
+        ):
             return True
         else:
             return False
     else:
         return False
-


Test patch:
diff --git a/tests/test_wrapper_funcs.py b/tests/test_wrapper_funcs.py
index e305c984..8f63ccb4 100644
--- a/tests/test_wrapper_funcs.py
+++ b/tests/test_wrapper_funcs.py
@@ -13,7 +13,7 @@
 import besca as bc
 import scanpy as sc
 from besca.st._wrapper_funcs import additional_labeling, highly_variable_genes
-
+from besca.Import._read import all_symbols_ok
 
 pytest.raw_data_subset_size = 1000
 
@@ -120,3 +120,43 @@ def test_highly_variable_genes(create_random_anndata_object: AnnData):
     # ensure that we get all hvgs and not just one
     assert adata.shape[0] == pytest.raw_data_subset_size
     assert adata.shape[1] == 608
+
+
+def test_all_symbols_ok():
+
+    good_symbols_list: List[str] = [
+        "AC004.2",
+        "AC43.3",
+        "A1",
+        "AC004.2",
+        "ACDF3",
+        "A..4A",
+        "YYYY",
+        "782387324A",
+        "Nature",
+        "GoodgenedNA",
+        "NAGene",
+        "abcNAcde",
+        "nature",
+        "HLA-DOB",
+        "Mafa-DQA",
+        "-ABC",
+    ]
+    good: bool = all_symbols_ok(symbols_list=good_symbols_list)
+    assert good == True
+
+    bad_symbols_list: List[str] = [
+        "434443",
+        "NA",
+        ".",
+        "...",
+        ".1",
+        ".NA",
+        "",
+        "na",
+        "Na",
+        "N/A",
+        "CORRECTGeneName",
+    ]
+    bad: bool = all_symbols_ok(symbols_list=bad_symbols_list)
+    assert bad == False