Accessing packages

Accessing packages#

from enviPath_python.enviPath import *
import getpass

As a first step to initialize the enviPath class, one needs to instantiate the id, in this case the host, from which data will be retrieved. This is set up in this way so that the user can decide which instance to use, i.e. prod, dev or for developers, their own local instance (http://localhost:8080/).

Each enviPath object also requires an id, as you might know from the documentation or other tutorials, ids are on enviPath URLs to the corresponding object page, in the example below, since we want the data contained on EAWAG-BBD package, we will therefore use the URL to EAWAG-BBD

HOST_INSTANCE = "https://envipath.org"
EAWAG_BBD_URL = "https://envipath.org/package/32de3cf4-e3e6-4168-956e-32fa5ddb0ce1"
eP = enviPath(HOST_INSTANCE)
pkg = Package(eP.requester, id=EAWAG_BBD_URL)
selected_pathways = pkg.get_pathways()[:2]
for pathway in selected_pathways:
    print(f"Pathway {pathway.get_name()} can be found on: {pathway.get_id()}")
---------------------------------------------------------------------------
JSONDecodeError                           Traceback (most recent call last)
File ~/checkouts/readthedocs.org/user_builds/envipath-python/envs/develop/lib/python3.10/site-packages/requests/models.py:976, in Response.json(self, **kwargs)
    975 try:
--> 976     return complexjson.loads(self.text, **kwargs)
    977 except JSONDecodeError as e:
    978     # Catch JSON-related errors and raise as requests.JSONDecodeError
    979     # This aliases json.JSONDecodeError and simplejson.JSONDecodeError

File ~/.asdf/installs/python/3.10.17/lib/python3.10/json/__init__.py:346, in loads(s, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)
    343 if (cls is None and object_hook is None and
    344         parse_int is None and parse_float is None and
    345         parse_constant is None and object_pairs_hook is None and not kw):
--> 346     return _default_decoder.decode(s)
    347 if cls is None:

File ~/.asdf/installs/python/3.10.17/lib/python3.10/json/decoder.py:337, in JSONDecoder.decode(self, s, _w)
    333 """Return the Python representation of ``s`` (a ``str`` instance
    334 containing a JSON document).
    335 
    336 """
--> 337 obj, end = self.raw_decode(s, idx=_w(s, 0).end())
    338 end = _w(s, end).end()

File ~/.asdf/installs/python/3.10.17/lib/python3.10/json/decoder.py:355, in JSONDecoder.raw_decode(self, s, idx)
    354 except StopIteration as err:
--> 355     raise JSONDecodeError("Expecting value", s, err.value) from None
    356 return obj, end

JSONDecodeError: Expecting value: line 3 column 1 (char 2)

During handling of the above exception, another exception occurred:

JSONDecodeError                           Traceback (most recent call last)
Cell In[2], line 5
      3 eP = enviPath(HOST_INSTANCE)
      4 pkg = Package(eP.requester, id=EAWAG_BBD_URL)
----> 5 selected_pathways = pkg.get_pathways()[:2]
      6 for pathway in selected_pathways:
      7     print(f"Pathway {pathway.get_name()} can be found on: {pathway.get_id()}")

File ~/checkouts/readthedocs.org/user_builds/envipath-python/envs/develop/lib/python3.10/site-packages/enviPath_python/objects.py:415, in Package.get_pathways(self)
    409 def get_pathways(self) -> List['Pathway']:
    410     """
    411     Gets all pathways of the package.
    412 
    413     :return: List of Pathway objects.
    414     """
--> 415     res = self.requester.get_objects(self.id + '/', Endpoint.PATHWAY)
    416     return res

File ~/checkouts/readthedocs.org/user_builds/envipath-python/envs/develop/lib/python3.10/site-packages/enviPath_python/enviPath.py:494, in enviPathRequester.get_objects(self, base_url, endpoint)
    485 """
    486 Generic get method to retrieve objects.
    487 
   (...)
    491 :return: List of objects denoted by endpoint.
    492 """
    493 url = base_url + endpoint.value
--> 494 objs = self.get_request(url).json()
    496 # Handly malformed reponse in case there are not entries
    497 if len(objs) == 0 or ('object' in objs and len(objs['object']) == 0):

File ~/checkouts/readthedocs.org/user_builds/envipath-python/envs/develop/lib/python3.10/site-packages/requests/models.py:980, in Response.json(self, **kwargs)
    976     return complexjson.loads(self.text, **kwargs)
    977 except JSONDecodeError as e:
    978     # Catch JSON-related errors and raise as requests.JSONDecodeError
    979     # This aliases json.JSONDecodeError and simplejson.JSONDecodeError
--> 980     raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)

JSONDecodeError: Expecting value: line 3 column 1 (char 2)

This works well for packages that are public. However, when one wants to access private data the login method from enviPath class must be invoked. We use this opportunity to recommend the usage of getpass library in order to avoid password leaks when sharing code among pears.

username = "myusername"
password = "mypassword" # We recommend to use here: getpass.getpass()

PRIVATE_PACKAGE_URL = "https://envipath.org/package/8dc6c079-d43f-4eb7-afda-fcacb94699a5"
try:
    eP.login(username, password)
    private_pkg = Package(eP.requester, id=PRIVATE_PACKAGE_URL)
except Exception as e:
    print(f"An exception is raised due to the dummy credentials we used: {e}")
An exception is raised due to the dummy credentials we used: Login Failed!

Finally, we show that one can review the amount of existing data on the reviewed packages with just a few lines of code. In this tutorial, we use Plotly to visualize the package statistics.

import pandas as pd
import plotly.graph_objects as go


# Get all reviewed packages
reviewed_packages = [
    Package(eP.requester, id=EAWAG_BBD_URL),
    Package(eP.requester, id="https://envipath.org/package/7932e576-03c7-4106-819d-fe80dc605b8a"), # EAWAG-SLUDGE
    Package(eP.requester, id="https://envipath.org/package/5882df9c-dae1-4d80-a40e-db4724271456") # EAWAG-SOIL
]

# Fetch all the relevant data
pkg_data = {}
for pkg in reviewed_packages:
    d = {}
    d["Compounds"] = len(pkg.get_compounds())
    d["Reactions"] = len(pkg.get_reactions())
    d["Rules"] = len(pkg.get_rules())
    d["Scenarios"] = len(pkg.get_scenarios())
    d["Pathways"] = len(pkg.get_pathways())
    pkg_data[pkg.get_name()] = d

data = pd.DataFrame(pkg_data)

Hide code cell source

fig = go.Figure()

# Generate a bar plot with a dropdown menu for a more comfortable selection and visualization of packages
button_list = [
    dict(
        label="All",
        method="update",
        args=[{"visible": [True]*len(data.columns)},
              {"title": "Package statistics of all reviewed packages"}])
]
for (i, package_name) in enumerate(data.columns):
    fig.add_trace(
        go.Bar(x=data.index, y=data[package_name], name=package_name, visible=i==0)
    )
    button = dict(
        label=package_name,
        method="update",
        args=[{"visible": [val==i for val in range(len(data.columns))]},
              {"title": f"Package statistics of {package_name}"}])
    button_list.append(button)
i = 0
fig.update_layout(
    title = f"Package statistics of {data.columns[i]}",
    updatemenus=[
        dict(
            active=i+1,
            buttons=list(button_list),
        )
    ])

fig