Source code for bio2bel.manager.bel_manager

# -*- coding: utf-8 -*-

"""Provide abstractions over BEL generation procedures."""

import os
from abc import ABC, abstractmethod

import click
from more_click import verbose_option

import pybel
from pybel import to_indra_statements
from pybel.cli import host_option
from .cli_manager import CliMixin
from ..constants import directory_option

__all__ = [
    'BELManagerMixin',
    'Bio2BELMissingEdgeModelError',
]


class Bio2BELMissingEdgeModelError(TypeError):
    """Raised when the edge_model class variable is not defined."""


[docs]class BELManagerMixin(ABC, CliMixin): """A mixin for generating a :class:`pybel.BELGraph` representing BEL. First, you'll have to make sure that :mod:`pybel` is installed. This can be done with pip like: .. code-block:: bash $ pip install pybel To use this mixin, you need to properly implement the :class:`bio2bel.AbstractManager`, and additionally define a function named ``to_bel`` that returns a BEL graph. .. code-block:: python >>> from bio2bel import AbstractManager >>> from bio2bel.manager.bel_manager import BELManagerMixin >>> from pybel import BELGraph >>> >>> class MyManager(AbstractManager, BELManagerMixin): ... def to_bel(self) -> BELGraph: ... pass """ edge_model = ...
[docs] def count_relations(self) -> int: """Count the number of BEL relations generated.""" if self.edge_model is ...: raise Bio2BELMissingEdgeModelError('edge_edge model is undefined/count_bel_relations is not overridden') elif isinstance(self.edge_model, list): return sum(self._count_model(m) for m in self.edge_model) else: return self._count_model(self.edge_model)
[docs] @abstractmethod def to_bel(self, *args, **kwargs) -> pybel.BELGraph: """Convert the database to BEL. Example implementation outline: .. code-block:: python from bio2bel import AbstractManager from bio2bel.manager.bel_manager import BELManagerMixin from pybel import BELGraph from .models import Interaction class MyManager(AbstractManager, BELManagerMixin): module_name = 'mirtarbase' def to_bel(self): rv = BELGraph( name='miRTarBase', version='1.0.0', ) for interaction in self.session.query(Interaction): mirna = mirna_dsl('mirtarbase', interaction.mirna.mirtarbase_id) rna = rna_dsl('hgnc', interaction.target.hgnc_id) rv.add_qualified_edge( mirna, rna, DECREASES, ... ) return rv """
[docs] def to_indra_statements(self, *args, **kwargs): """Dump as a list of INDRA statements. :rtype: List[indra.Statement] """ graph = self.to_bel(*args, **kwargs) return to_indra_statements(graph)
@staticmethod def _cli_add_to_bel(main: click.Group) -> click.Group: """Add the export BEL command.""" return add_cli_to_bel(main) @staticmethod def _cli_add_upload_bel(main: click.Group) -> click.Group: """Add the upload BEL command.""" return add_cli_upload_bel(main)
[docs] @classmethod def get_cli(cls) -> click.Group: """Get a :mod:`click` main function with added BEL commands.""" main = super().get_cli() @main.group() def bel(): """Manage BEL.""" cls._cli_add_to_bel(bel) cls._cli_add_upload_bel(bel) return main
def add_cli_to_bel(main: click.Group) -> click.Group: """Add several command to main :mod:`click` function related to export to BEL.""" @main.command() @click.option('-o', '--output') @verbose_option @click.pass_obj def write(manager: BELManagerMixin, output: str): """Write as BEL Script.""" graph = manager.to_bel() click.echo(graph.summary_str()) pybel.dump(graph, output) @main.command() @directory_option @verbose_option @click.pass_obj def write_edgelist(manager: BELManagerMixin, directory: str): """Write as an edge list and node list file.""" graph = manager.to_bel() edgelist_path = os.path.join(directory, f'{manager.module_name}.edgelist') nodelist_path = os.path.join(directory, 'node_list.txt') node_to_id = {} with open(nodelist_path, 'w') as file: print('index', 'node', 'type', file=file) # noqa:T001 for i, node in enumerate(sorted(graph)): print(i, node, node.function, file=file) # noqa:T001 node_to_id[node] = i with open(edgelist_path, 'w') as file: for u, v in graph.edges(): print(node_to_id[u], node_to_id[v], file=file) # noqa:T001 return main def add_cli_upload_bel(main: click.Group) -> click.Group: # noqa: D202 """Add several command to main :mod:`click` function related to export to BEL.""" @main.command() @host_option @verbose_option @click.pass_obj def upload(manager: BELManagerMixin, host: str): """Upload BEL to BEL Commons.""" graph = manager.to_bel() pybel.to_bel_commons(graph, host=host, public=True) return main