Repository: sorgerlab/indra

Issue:
Unhandled namespace: TAX in process_pybel_graph()
Hi folks, I wanted to convert BEL statements to English using your excellent `EnglishAssembly.make_model()` method but a couple statements could not be parsed because they included a grounded term from the NCBI Taxonomy namespace which was not available in [`indra.sources.bel.processor.get_db_refs_by_name()`](https://github.com/sorgerlab/indra/blob/7394532b4afc2845c9f088197070a343772329f8/indra/sources/bel/processor.py#L441)


This was the message I got when running the following code:
```python
il6_amp = pybel.from_biodati('...')
from indra.assemblers.english import EnglishAssembler
from indra.sources.bel.api import process_pybel_graph
pbp = process_pybel_graph(il6_amp)
stmts = pbp.statements
stmts
```

```
INFO: [2020-05-30 07:14:20] indra.sources.bel.processor - Unhandled namespace: TAX: Severe acute respiratory syndrome coronavirus 2 (a(TAX:"Severe acute respiratory syndrome coronavirus 2"))
INFO: [2020-05-30 07:14:20] indra.sources.bel.processor - Unable to get identifier information for node: a(TAX:"Severe acute respiratory syndrome coronavirus 2")
INFO: [2020-05-30 07:14:20] indra.sources.bel.processor - Unhandled namespace: TAX: Severe acute respiratory syndrome coronavirus 2 (a(TAX:"Severe acute respiratory syndrome coronavirus 2"))
INFO: [2020-05-30 07:14:20] indra.sources.bel.processor - Unable to get identifier information for node: a(TAX:"Severe acute respiratory syndrome coronavirus 2")
```

Comments:

Patch:
diff --git a/doc/modules/databases/index.rst b/doc/modules/databases/index.rst
index ac9fc2846..8791677d7 100644
--- a/doc/modules/databases/index.rst
+++ b/doc/modules/databases/index.rst
@@ -98,3 +98,8 @@ Disease Ontology (DOID) client (:py:mod:`indra.databases.doid_client`)
 ----------------------------------------------------------------------
 .. automodule:: indra.databases.doid_client
     :members:
+
+Taxonomy client (:py:mod:`indra.databases.taxonomy_client`)
+-----------------------------------------------------------
+.. automodule:: indra.databases.taxonomy_client
+    :members:
diff --git a/indra/databases/taxonomy_client.py b/indra/databases/taxonomy_client.py
new file mode 100644
index 000000000..b257739b8
--- /dev/null
+++ b/indra/databases/taxonomy_client.py
@@ -0,0 +1,38 @@
+"""Client to access the Entrez Taxonomy web service."""
+import requests
+
+base_url = 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi'
+
+
+def _send_search_request(term):
+    params = {
+        'db': 'taxonomy',
+        'term': term,
+        'retmode': 'json'
+        }
+    res = requests.get(base_url, params=params)
+    if not res.status_code == 200:
+        return None
+    return res.json().get('esearchresult')
+
+
+def get_taxonomy_id(name):
+    """Return the taxonomy ID corresponding to a taxonomy name.
+
+    Parameters
+    ----------
+    name : str
+        The name of the taxonomy entry.
+        Example: "Severe acute respiratory syndrome coronavirus 2"
+
+    Returns
+    -------
+    str or None
+        The taxonomy ID corresponding to the given name or None
+        if not available.
+    """
+    res = _send_search_request(name)
+    idlist = res.get('idlist')
+    if not idlist:
+        return None
+    return idlist[0]
diff --git a/indra/sources/bel/processor.py b/indra/sources/bel/processor.py
index 9e71e37bd..22e0093c5 100644
--- a/indra/sources/bel/processor.py
+++ b/indra/sources/bel/processor.py
@@ -14,7 +14,7 @@ from indra.statements import *
 from indra.sources.bel.rdf_processor import bel_to_indra, chebi_name_id
 from indra.databases import (
     chebi_client, go_client, hgnc_client, mesh_client,
-    mirbase_client, uniprot_client,
+    mirbase_client, uniprot_client, taxonomy_client
 )
 from indra.assemblers.pybel.assembler import _pybel_indra_act_map
 
@@ -575,6 +575,12 @@ def get_db_refs_by_name(ns, name, node_data):
     # SDIS, SCHEM: Include the name as the ID for the namespace
     elif ns in ('SDIS', 'SCHEM', 'TEXT'):
         db_refs = {ns: name}
+    elif ns == 'TAX':
+        tid = taxonomy_client.get_taxonomy_id(name)
+        if tid:
+            db_refs = {'TAXONOMY': tid}
+        else:
+            logger.info('Could not get taxonomy ID for %s' % name)
     else:
         logger.info("Unhandled namespace: %s: %s (%s)" % (ns, name,
                                                           node_data))


Test patch:
diff --git a/indra/tests/test_taxonomy_client.py b/indra/tests/test_taxonomy_client.py
new file mode 100644
index 000000000..c812d854e
--- /dev/null
+++ b/indra/tests/test_taxonomy_client.py
@@ -0,0 +1,6 @@
+from indra.databases import taxonomy_client
+
+
+def test_name_lookup():
+    assert taxonomy_client.get_taxonomy_id(
+        'Severe acute respiratory syndrome coronavirus 2') == '2697049'