Пример #1
0
def write_nodes(nx_graph, py_graph):

    # Defer importation of optional runtime dependencies until necessary.
    pydot = libs.import_runtime_optional('pydot')

    for nx_node_name in nx_graph.node:
        nx_dic = nx_graph.node[nx_node_name]

        clr = nx_dic.get('color', None)
        fntclr = nx_dic.get('fontcolor', None)
        fntnm = nx_dic.get('fontname', None)
        fntsz = nx_dic.get('fontsize', None)
        shp = nx_dic.get('shape', None)
        stl = nx_dic.get('style', None)

        # if (clr is not None and fntclr is not None and fntnm is not None and shp is not None and
        #             shp is not None and stl is not None):

        nde = pydot.Node(nx_node_name,
                         color=clr,
                         fontcolor=fntclr,
                         fontname=fntnm,
                         fontsize=fntsz,
                         shape=shp,
                         style=stl)

        py_graph.add_node(nde)

        # else:
        #
        #     logs.log_warning("WARNING! You have requested a sub-graph node that does not exist!\n"
        #                      " Ignoring request!")

    return py_graph
Пример #2
0
def get_distro_version() -> str:
    '''
    Human-readable ``.``-delimited version specifier string of the current
    platform.

    Specifically, This function returns:

    * Under Linux, the version reported by this Linux distribution as follows:

      * If the deprecated :func:`platform.linux_distribution` function is still
        defined, the second element of the 3-tuple returned by this function
        (e.g., ``6.4``).
      * Else if the third-party Linux-specific "distro" package (referenced
    # by official Python documentation as a stand-in replacement for the
    # deprecated Linux-specific platform.linux_distribution() function) is
    # importable, defer to this package.
      * Else, the string returned by the :func:`platform.release` function.
        Since this is probably the non-human-readable ``.``- and
        ``-``-delimited version specifier string of the current Linux kernel
        (e.g., ``4.1.15-gentoo-r1``), this is only a fallback.
    '''

    # Avoid circular import dependencies.
    from betse.lib import libs
    from betse.util.io.error.errwarning import ignoring_deprecations

    # Version specifier to be returned.
    distro_version = None

    # If the deprecated Linux-specific platform.linux_distribution()
    # function is still defined...
    if hasattr(platform, 'linux_distribution'):
        # Ignore all deprecations emitted by Python 3.5 through 3.7 concerning
        # the pending removal of the platform.linux_distribution() function...
        with ignoring_deprecations():
            # Defer to the second item of the 3-tuple "(distname, version, id)"
            # returned by this function (e.g., "6.4"). Since platform.release()
            # returns the low-level kernel version (e.g., "4.1.15"), the latter
            # version is ignored if feasible.
            distro_version = platform.linux_distribution()[1]
    # Else if the optional third-party Linux-specific "distro" package is
    # importable, defer to this package.
    elif libs.is_runtime_optional('distro'):
        # Import this package.
        distro = libs.import_runtime_optional('distro')

        # For disambiguity, prefer the "best" (i.e., most specific and
        # accurate) version specifier published by this Linux distribution.
        distro_version = distro.version(best=True)
    # Else, this is Python >= 3.8 *AND* the "distro" package is unimportable.
    # In this case, default to the version specifier returned by the
    # platform.release() function. Since this typically corresponds to the
    # low-level version of the current kernel (e.g., "4.1.15") rather than the
    # high-level version of the current Linux distribution (e.g., "6.4"), this
    # is a fallback of last resort.
    else:
        distro_version = platform.release()

    # Return this version specifier.
    return distro_version
Пример #3
0
def get_distro_name() -> str:
    '''
    Human-readable name of the current Linux distribution.

    Specifically, this function returns:

    * If the :func:`platform.linux_distribution` function is available, the
      first element of the 3-tuple returned by this function (e.g.,
      ``CentOS``).
    * Else, the string returned by the :func:`platform.system` function.
      Since this is probably the generic string ``Linux``, this is only a
      fallback.
    '''

    # Avoid circular import dependencies.
    from betse.lib import libs
    from betse.util.io.error.errwarning import ignoring_deprecations
    from betse.util.os.brand import windows

    # Linux distribution name to be returned.
    distro_name = None

    # If the deprecated Linux-specific platform.linux_distribution()
    # function is still defined...
    if hasattr(platform, 'linux_distribution'):
        # Ignore all deprecations emitted by Python 3.5 through 3.7 concerning
        # the pending removal of the platform.linux_distribution() function...
        with ignoring_deprecations():
            # Defer to the second item of the 3-tuple "(distname, version, id)"
            # Defer to the first item of the 3-tuple "(distname, version, id)"
            # returned by this function (e.g., "CentOS"). Since
            # platform.system() returns the low-level kernel name "Linux", the
            # latter name is ignored if feasible.
            distro_name = platform.linux_distribution()[0]
    # Else if the optional third-party Linux-specific "distro" package is
    # importable, defer to this package.
    elif libs.is_runtime_optional('distro'):
        # Import this package.
        distro = libs.import_runtime_optional('distro')

        # Defer to the name reported by this package.
        distro_name = distro.name()
    # Else if this is actually the Windows Subsystem for Linux (WSL)
    # masquerading as Linux, return "Windows (WSL)" rather than "Linux".
    elif windows.is_windows_wsl():
        distro_name = 'Windows (WSL)'
    # Else, this is Python >= 3.8 *AND* the "distro" package is unimportable.
    # In this case, default to the platform name returned by the
    # platform.system() function. Since this typically corresponds to the
    # low-level name of the current kernel (e.g., "Linux") rather than the
    # high-level name of the current Linux distribution (e.g., "Arch",
    # "Gentoo"), this is only a fallback of last resort.
    else:
        distro_name = platform.system()

    # Return this version specifier.
    return distro_name
Пример #4
0
def write_edges(nx_graph, py_graph):

    # Defer importation of optional runtime dependencies until necessary.
    pydot = libs.import_runtime_optional('pydot')

    for na, nb in nx_graph.edges():
        edge_dic = nx_graph.edge[na][nb]

        arrow = edge_dic.get('arrowhead', None)
        linew = edge_dic.get('penwidth', None)
        clr = edge_dic.get('color', 'black')

        # if arrow is not None and linew is not None and clr is not None:

        eg = pydot.Edge(na, nb, arrowhead=arrow, penwidth=linew, color=clr)
        py_graph.add_edge(eg)

        # else:
        #
        #     logs.log_warning("WARNING! You have requested a sub-graph edge that does not exist!\n"
        #                      " Ignoring request!")

    return py_graph
Пример #5
0
def graph_influencers(
    self,
    base_graph,
    name,
    a_list,
    i_list,
    p,
    reaction_zone='cell',
    zone_tags_a=None,
    zone_tags_i=None,
) -> None:
    '''
    Allow activators and inhibitors, which have various options, to be added to
    a graph.

    Parameters
    --------------
    graph:    The pydot graph object to add to
    name             Name of the main molecule being activated or inhibited
    a_list:   List of activator names
    i_list:   List of inhibitor names
    reaction_zone:  Zone for the main reaction
    zone_tags_a:     list of zones activator works from
    zone_tags_i:     list of zones inhibitor work from.

    Returns
    --------
    graph           Updated pydot graph object
    '''

    # Defer importation of optional runtime dependencies until necessary.
    pydot = libs.import_runtime_optional('pydot')

    if a_list != 'None' and a_list is not None:
        for act_name, zone_a in zip(a_list, zone_tags_a):
            if act_name.endswith(
                    '!'):  # if activator indicated to be independent
                # make the name in accordance with its actual identifier
                act_name = act_name[:-1]

            if reaction_zone == 'mit':
                act_name += '_mit'
                nde = pydot.Node(
                    act_name,
                    style='filled',
                    color=self.conc_node_color,
                    shape=self.conc_shape,
                    fontcolor=self.conc_node_font_color,
                    fontname=self.net_font_name,
                    fontsize=self.node_font_size,
                )
                base_graph.add_node(nde)

            if zone_a == 'env':
                act_name = act_name + '_env'
                nde = pydot.Node(
                    act_name,
                    style='filled',
                    color=self.conc_node_color,
                    shape=self.conc_shape,
                    fontcolor=self.conc_node_font_color,
                    fontname=self.net_font_name,
                    fontsize=self.node_font_size,
                )
                base_graph.add_node(nde)

            base_graph.add_edge(
                pydot.Edge(act_name,
                           name,
                           penwidth=self.edge_width,
                           arrowhead='dot',
                           color='blue'))

    if i_list != 'None' and i_list is not None:
        for inh_name, zone_i in zip(i_list, zone_tags_i):
            if reaction_zone == 'mit':
                inh_name += '_mit'
                nde = pydot.Node(
                    inh_name,
                    style='filled',
                    color=self.conc_node_color,
                    shape=self.conc_shape,
                    fontcolor=self.conc_node_font_color,
                    fontname=self.net_font_name,
                    fontsize=self.node_font_size,
                )
                base_graph.add_node(nde)

            if zone_i == 'env':
                inh_name = inh_name + '_env'
                nde = pydot.Node(
                    inh_name,
                    style='filled',
                    color=self.conc_node_color,
                    shape=self.conc_shape,
                    fontcolor=self.conc_node_font_color,
                    fontname=self.net_font_name,
                    fontsize=self.node_font_size,
                )
                base_graph.add_node(nde)

            base_graph.add_edge(
                pydot.Edge(inh_name,
                           name,
                           arrowhead='tee',
                           color='red',
                           penwidth=self.edge_width))
Пример #6
0
def make_subgraphs(self, base_graph, p):

    # Defer importation of optional runtime dependencies until necessary.
    pydot, networkx = libs.import_runtime_optional('pydot', 'networkx')

    # Convert the pydot-version base_graph into a networkx function so we can
    # re-jigger nodes and make subgraphs.
    net_all = networkx.from_pydot(base_graph)

    subnetworks = {}

    master_graph = pydot.Dot(
        graph_type='digraph',
        concentrate=False,
        nodesep=0.1,
        ranksep=0.3,
        splines=True,
        strict=True,
        rankdir=self.net_layout,
    )

    # Begin by writing all nodes and edges from the main network to the new pydot network
    master_graph = write_nodes(net_all, master_graph)
    master_graph = write_edges(net_all, master_graph)

    for subnet_opts in self.subnets_dicts:
        subnet_name = subnet_opts['name']
        subnet_nodes = subnet_opts['nodes']

        # expand subnetwork nodes list with nearest neighbours from main graph:
        extended_node_list = []

        for nde in subnet_nodes:
            if nde in net_all.nodes():
                extended_node_list.append(nde)
                nn = net_all.neighbors(nde)

                for n in nn:
                    extended_node_list.append(n)

        # reassign subgraph nodes to the extended list:
        subnet_nodes = extended_node_list

        tit_font = subnet_opts['title font color']
        box_color = subnet_opts['box shading color']

        subnet = networkx.subgraph(net_all, subnet_nodes)
        subnetworks[subnet_name] = {
            'name': subnet_name,
            'nx subnet': subnet,
            'tit_font': tit_font,
            'box_color': box_color,
            'nodes': subnet_nodes,
        }

    for i, sn_dic in enumerate(subnetworks):
        cname = 'cluster_' + str(i)

        # declare subgraphs in pydot format:
        py_sub = pydot.Subgraph(
            cname,
            label=subnetworks[sn_dic]['name'],
            style='filled',
            fontcolor=subnetworks[sn_dic]['tit_font'],
            fontname=self.net_font_name,
            fontsize=self.tit_font_size,
            color=subnetworks[sn_dic]['box_color'],
        )

        subnetworks[sn_dic]['py subnet'] = py_sub

    # now each subnetwork has a networkx and empty pydot subgraph definition.
    # write each networkx subnet to the pydot subgraph:
    for i, sn_dic in enumerate(subnetworks):
        sn_py = write_nodes(subnetworks[sn_dic]['nx subnet'],
                            subnetworks[sn_dic]['py subnet'])
        subnetworks[sn_dic]['py subnet'] = sn_py

        master_graph.add_subgraph(sn_py)
        master_graph = write_edges(subnetworks[sn_dic]['nx subnet'],
                                   master_graph)

    return master_graph
Пример #7
0
def plot_master_network(self, p):

    # Defer importation of optional runtime dependencies until necessary.
    pydot = libs.import_runtime_optional('pydot')

    # create a graph object
    base_graph = pydot.Dot(
        graph_type='digraph',
        concentrate=False,
        nodesep=0.1,
        ranksep=0.3,
        splines=True,
        strict=True,
        rankdir=self.net_layout,
    )

    # add Vmem to the graph
    nde = pydot.Node(
        'Vmem',
        style='filled',
        shape=self.vmem_shape,
        color=self.vmem_node_color,
        fontcolor=self.vmem_node_font_color,
        fontname=self.net_font_name,
        fontsize=self.node_font_size,
    )
    base_graph.add_node(nde)

    # add each substance as a node in the graph:
    for i, (name, val) in enumerate(self.cell_concs.items()):
        if name not in p.ions_dict:
            mol = self.molecules[name]

            nde = pydot.Node(
                name,
                style='filled',
                color=self.conc_node_color,
                shape=self.conc_shape,
                fontcolor=self.conc_node_font_color,
                fontname=self.net_font_name,
                fontsize=self.node_font_size,
            )
            base_graph.add_node(nde)

            if mol.simple_growth:
                # add node & edge for growth reaction component:
                rea_name = name + '_growth'
                rea_node = pydot.Node(
                    rea_name,
                    style='filled',
                    color=self.react_node_color,
                    shape=self.reaction_shape,
                    fontcolor=self.react_node_font_color,
                    fontname=self.net_font_name,
                    fontsize=self.node_font_size,
                )

                base_graph.add_node(rea_node)

                # if the substance has autocatalytic growth capacity add the edge in:
                base_graph.add_edge(
                    pydot.Edge(
                        rea_name,
                        name,
                        arrowhead='normal',
                        coeff=1.0,
                        penwidth=self.edge_width,
                    ))

                # add node & edge for decay reaction component:
                rea_name = name + '_decay'
                rea_node = pydot.Node(
                    rea_name,
                    style='filled',
                    color=self.react_node_color,
                    shape=self.reaction_shape,
                    fontcolor=self.react_node_font_color,
                    fontname=self.net_font_name,
                    fontsize=self.node_font_size,
                )

                base_graph.add_node(rea_node)

                # if the substance has autocatalytic decay capacity add the edge in:
                base_graph.add_edge(
                    pydot.Edge(
                        name,
                        rea_name,
                        arrowhead='normal',
                        coeff=1.0,
                        penwidth=self.edge_width,
                    ))

            if mol.ion_channel_gating:
                # if this substance gates for ion channels:

                # define a node corresponding to the ion channel:
                gated_node = pydot.Node(
                    mol.gating_channel_name,
                    style='filled',
                    color=self.chan_node_color,
                    shape=self.channel_shape,
                    fontcolor=self.chan_node_font_color,
                    fontname=self.net_font_name,
                    fontsize=self.node_font_size,
                )
                base_graph.add_node(gated_node)

                # add the nodes for substance gating channel, if needed:
                if mol.gating_extracell:
                    substance_name = name + "_env"

                    nde = pydot.Node(
                        name,
                        style='filled',
                        color=self.conc_node_color,
                        shape=self.conc_shape,
                        fontcolor=self.conc_node_font_color,
                        fontname=self.net_font_name,
                        fontsize=self.node_font_size,
                    )
                    base_graph.add_node(nde)

                else:
                    substance_name = name

                base_graph.add_edge(
                    pydot.Edge(
                        substance_name,
                        gated_node,
                        arrowhead='dot',
                        color='blue',
                        penwidth=self.edge_width,
                    ))

                for ion_name in mol.gating_ion_name:
                    ion_Pmem = 'Pmem_' + ion_name

                    # add the edges for channel effect on ion concentration:
                    base_graph.add_edge(
                        pydot.Edge(
                            gated_node,
                            ion_Pmem,
                            arrowhead='dot',
                            color='blue',
                            penwidth=self.edge_width,
                        ))

        else:  # add the ion as a node, but don't worry about growth/decay
            nde = pydot.Node(
                name,
                style='filled',
                color=self.conc_node_color,
                shape=self.conc_shape,
                fontcolor=self.conc_node_font_color,
                fontname=self.net_font_name,
                fontsize=self.node_font_size,
            )
            base_graph.add_node(nde)

        # add expression nodes for electrodiffusion/diffusion:
        # check the Dmem value of the substance:
        dmem_check = self.Dmem[name]

        # FIXME here is one place where Vmem can activate/inhibit the reaction itself...
        if dmem_check != 0.0:
            react_label = 'Pmem_' + name  # here, "Pmem_" stands for membrane permeability
            nde = pydot.Node(
                react_label,
                style='filled',
                color=self.ed_node_color,
                shape=self.ed_shape,
                fontcolor=self.ed_node_font_color,
                fontname=self.net_font_name,
                fontsize=self.node_font_size,
            )

            base_graph.add_node(nde)

            # add the environmental complement for this substance:
            name_env = name + '_env'
            nde = pydot.Node(
                name_env,
                style='filled',
                color=self.conc_node_color,
                shape=self.conc_shape,
                fontcolor=self.conc_node_font_color,
                fontname=self.net_font_name,
                fontsize=self.node_font_size,
            )

            base_graph.add_node(nde)

            base_graph.add_edge(
                pydot.Edge(
                    name,
                    react_label,
                    arrowhead='normal',
                    coeff=1.0,
                    penwidth=self.edge_width,
                ))

            base_graph.add_edge(
                pydot.Edge(
                    react_label,
                    name_env,
                    arrowhead='normal',
                    coeff=1.0,
                    penwidth=self.edge_width,
                ))

    # Deal with activators and inhibitors for substance growth.
    for i, name in enumerate(self.molecules):
        mol = self.molecules[name]
        # add regulatory as nodes in the graph:

        if mol.simple_growth:
            gname = name + '_growth'

            graph_influencers(self,
                              base_graph,
                              gname,
                              mol.growth_activators_list,
                              mol.growth_inhibitors_list,
                              p,
                              reaction_zone='cell',
                              zone_tags_a=mol.growth_activators_zone,
                              zone_tags_i=mol.growth_inhibitors_zone)

        if mol.ion_channel_gating:
            graph_influencers(self,
                              base_graph,
                              mol.gating_channel_name,
                              mol.ion_activators_list,
                              mol.ion_inhibitors_list,
                              p,
                              reaction_zone='cell',
                              zone_tags_a=mol.ion_activators_zone,
                              zone_tags_i=mol.ion_inhibitors_zone)

    #--------------------------------------------------------------------------
    # Basic Bioelectric relations

    # detail how Vmem is affected via membrane permeability relationships to core ions:
    base_graph.add_edge(
        pydot.Edge('Pmem_Na',
                   'Vmem',
                   arrowhead='dot',
                   color='blue',
                   penwidth=self.edge_width))
    base_graph.add_edge(
        pydot.Edge('Pmem_K',
                   'Vmem',
                   arrowhead='tee',
                   color='red',
                   penwidth=self.edge_width))
    base_graph.add_edge(
        pydot.Edge('K_env',
                   'Vmem',
                   arrowhead='dot',
                   color='blue',
                   penwidth=self.edge_width))

    #--------------------------------------------------------------------------

    # if there are any reactions in the cytosol, add them to the graph
    if len(self.reactions) > 0:
        for i, name in enumerate(self.reactions):
            nde = pydot.Node(
                name,
                style='filled',
                color=self.react_node_color,
                shape=self.reaction_shape,
                fontcolor=self.react_node_font_color,
                fontname=self.net_font_name,
                fontsize=self.node_font_size,
            )
            base_graph.add_node(nde)

    if len(self.reactions_env) > 0:
        for i, name in enumerate(self.reactions_env):
            nde = pydot.Node(
                name,
                style='filled',
                color=self.react_node_color,
                shape=self.reaction_shape,
                fontcolor=self.react_node_font_color,
                fontname=self.net_font_name,
                fontsize=self.node_font_size,
            )
            base_graph.add_node(nde)

    # If there are any reactions in the mitochondria, add them to the graph.
    if len(self.reactions_mit) > 0:
        for i, name in enumerate(self.reactions_mit):
            nde = pydot.Node(name,
                             style='filled',
                             color=self.react_node_color,
                             shape=self.reaction_shape,
                             fontcolor=self.react_node_font_color,
                             fontname=self.net_font_name,
                             fontsize=self.node_font_size)
            base_graph.add_node(nde)

    # If there are any env reactions, plot their edges on the graph.
    if len(self.reactions_env) > 0:
        for i, name in enumerate(self.reactions_env):
            rea = self.reactions_env[name]

            for i, react_name in enumerate(rea.reactants_list):
                rea_coeff = rea.reactants_coeff[i]
                react_name_e = react_name + '_env'

                nde = pydot.Node(
                    react_name_e,
                    style='filled',
                    color=self.conc_node_color,
                    shape=self.conc_shape,
                    fontcolor=self.conc_node_font_color,
                    fontname=self.net_font_name,
                    fontsize=self.node_font_size,
                )

                base_graph.add_node(nde)
                base_graph.add_edge(
                    pydot.Edge(
                        react_name_e,
                        name,
                        arrowhead='normal',
                        coeff=rea_coeff,
                        penwidth=self.edge_width,
                    ))

            for j, prod_name in enumerate(rea.products_list):
                prod_coeff = rea.products_coeff[j]
                prod_name_e = prod_name + '_env'

                nde = pydot.Node(
                    prod_name_e,
                    style='filled',
                    color=self.conc_node_color,
                    shape=self.conc_shape,
                    fontcolor=self.conc_node_font_color,
                    fontname=self.net_font_name,
                    fontsize=self.node_font_size,
                )

                base_graph.add_node(nde)
                base_graph.add_edge(
                    pydot.Edge(
                        name,
                        prod_name_e,
                        arrowhead='normal',
                        coeff=prod_coeff,
                        penwidth=self.edge_width,
                    ))

            graph_influencers(self,
                              base_graph,
                              name,
                              rea.reaction_activators_list,
                              rea.reaction_inhibitors_list,
                              p,
                              reaction_zone=rea.reaction_zone,
                              zone_tags_a=rea.reaction_activators_zone,
                              zone_tags_i=rea.reaction_inhibitors_zone)

    # If there are any reactions, plot their edges on the graph.
    if len(self.reactions) > 0:
        for i, name in enumerate(self.reactions):
            rea = self.reactions[name]

            for i, react_name in enumerate(rea.reactants_list):
                rea_coeff = rea.reactants_coeff[i]
                base_graph.add_edge(
                    pydot.Edge(react_name,
                               name,
                               arrowhead='normal',
                               coeff=rea_coeff,
                               penwidth=self.edge_width))

            for j, prod_name in enumerate(rea.products_list):
                prod_coeff = rea.products_coeff[j]
                base_graph.add_edge(
                    pydot.Edge(name,
                               prod_name,
                               arrowhead='normal',
                               coeff=prod_coeff,
                               penwidth=self.edge_width))

            graph_influencers(self,
                              base_graph,
                              name,
                              rea.reaction_activators_list,
                              rea.reaction_inhibitors_list,
                              p,
                              reaction_zone=rea.reaction_zone,
                              zone_tags_a=rea.reaction_activators_zone,
                              zone_tags_i=rea.reaction_inhibitors_zone)

    # If there are any mitochondria zone reactions, plot their edges on the
    # graph (and react/prod nodes).
    if len(self.reactions_mit) > 0:
        for i, name in enumerate(self.reactions_mit):
            rea = self.reactions_mit[name]

            for i, react_name in enumerate(rea.reactants_list):
                react_name += '_mit'

                nde = pydot.Node(react_name,
                                 style='filled',
                                 color=self.conc_node_color,
                                 shape=self.conc_shape,
                                 fontcolor=self.conc_node_font_color,
                                 fontname=self.net_font_name,
                                 fontsize=self.node_font_size)

                base_graph.add_node(nde)

                rea_coeff = rea.reactants_coeff[i]
                base_graph.add_edge(
                    pydot.Edge(react_name,
                               name,
                               arrowhead='normal',
                               coeff=rea_coeff,
                               penwidth=self.edge_width))

            for j, prod_name in enumerate(rea.products_list):
                prod_name += '_mit'

                nde = pydot.Node(
                    prod_name,
                    style='filled',
                    color=self.conc_node_color,
                    shape=self.conc_shape,
                    fontcolor=self.conc_node_font_color,
                    fontname=self.net_font_name,
                    fontsize=self.node_font_size,
                )
                base_graph.add_node(nde)

                prod_coeff = rea.products_coeff[j]
                base_graph.add_edge(
                    pydot.Edge(name,
                               prod_name,
                               arrowhead='normal',
                               coeff=prod_coeff,
                               penwidth=self.edge_width))

            graph_influencers(self,
                              base_graph,
                              name,
                              rea.reaction_activators_list,
                              rea.reaction_inhibitors_list,
                              p,
                              reaction_zone=rea.reaction_zone,
                              zone_tags_a=rea.reaction_activators_zone,
                              zone_tags_i=rea.reaction_inhibitors_zone)

    # If there are any transporters, plot them on the graph.
    if len(self.transporters) > 0:
        for name in self.transporters:
            nde = pydot.Node(
                name,
                style='filled',
                color=self.transp_node_color,
                shape=self.transporter_shape,
                fontcolor=self.transp_node_font_color,
                fontname=self.net_font_name,
                fontsize=self.node_font_size,
            )

            base_graph.add_node(nde)

        for name in self.transporters:
            trans = self.transporters[name]

            for i, (react_name, tag) in enumerate(
                    zip(trans.reactants_list, trans.react_transport_tag)):
                rea_coeff = trans.reactants_coeff[i]

                if tag == 'cell_concs' or tag == 'mem_concs':
                    base_graph.add_edge(
                        pydot.Edge(
                            react_name,
                            name,
                            arrowhead='normal',
                            coeff=rea_coeff,
                            penwidth=self.edge_width,
                        ))

                else:
                    if tag == 'env_concs':
                        react_name += '_env'

                    elif tag == 'mit_concs':
                        react_name += '_mit'

                    nde = pydot.Node(
                        react_name,
                        style='filled',
                        color=self.conc_node_color,
                        shape=self.conc_shape,
                        fontcolor=self.conc_node_font_color,
                        fontname=self.net_font_name,
                        fontsize=self.node_font_size,
                    )

                    base_graph.add_node(nde)
                    base_graph.add_edge(
                        pydot.Edge(
                            react_name,
                            name,
                            arrowhead='normal',
                            coeff=rea_coeff,
                            penwidth=self.edge_width,
                        ))

            for j, (prod_name, tag) in enumerate(
                    zip(trans.products_list, trans.prod_transport_tag)):
                prod_coeff = trans.products_coeff[j]

                if tag == 'cell_concs' or tag == 'mem_concs':
                    base_graph.add_edge(
                        pydot.Edge(
                            name,
                            prod_name,
                            arrowhead='normal',
                            coeff=prod_coeff,
                            penwidth=self.edge_width,
                        ))

                else:
                    if tag == 'env_concs':
                        prod_name += '_env'

                    elif tag == 'mit_concs':
                        prod_name += '_mit'

                    nde = pydot.Node(
                        prod_name,
                        style='filled',
                        color=self.conc_node_color,
                        shape=self.conc_shape,
                        fontcolor=self.conc_node_font_color,
                        fontname=self.net_font_name,
                        fontsize=self.node_font_size,
                    )

                    base_graph.add_node(nde)
                    base_graph.add_edge(
                        pydot.Edge(
                            name,
                            prod_name,
                            arrowhead='normal',
                            coeff=prod_coeff,
                            penwidth=self.edge_width,
                        ))

            graph_influencers(self,
                              base_graph,
                              name,
                              trans.transporter_activators_list,
                              trans.transporter_inhibitors_list,
                              p,
                              reaction_zone=trans.reaction_zone,
                              zone_tags_a=trans.transporter_activators_zone,
                              zone_tags_i=trans.transporter_inhibitors_zone)

    # If there are any channels, plot their type, ion  and Vmem relationships
    # in the graph.
    if len(self.channels) > 0:
        for i, name in enumerate(self.channels):
            chan = self.channels[name]
            chan_class = self.channels[name].channel_class
            channel_name = self.channels[name].channel_type

            #FIXME: Consider refactoring to use dictionary lookups. Turtle toes!
            if chan_class == 'Na':
                ion_name = ['Na']

            elif chan_class == 'K':
                ion_name = ['K']

            elif chan_class == 'Kir':
                ion_name = ['K']

            elif chan_class == 'Fun':
                ion_name = ['Na', 'K']

            elif chan_class == 'Ca':
                ion_name = ['Ca']

            elif chan_class == 'NaP':
                ion_name = ['Na']

            elif chan_class == 'Cat':
                ion_name = ['Na', 'K']

            elif chan_class == 'Cl':
                ion_name = ['Cl']

            else:
                ion_name = []

            # add the channel to the diagram:
            nde = pydot.Node(
                name,
                style='filled',
                color=self.chan_node_color,
                shape=self.channel_shape,
                fontcolor=self.chan_node_font_color,
                fontname=self.net_font_name,
                fontsize=self.node_font_size,
            )

            base_graph.add_node(nde)

            for ion_n in ion_name:
                ion_Pmem = 'Pmem_' + ion_n

                base_graph.add_edge(
                    pydot.Edge(
                        name,
                        ion_Pmem,
                        arrowhead='dot',
                        color='blue',
                        penwidth=self.edge_width,
                    ))

            graph_influencers(self,
                              base_graph,
                              name,
                              chan.channel_activators_list,
                              chan.channel_inhibitors_list,
                              p,
                              reaction_zone='cell',
                              zone_tags_a=chan.channel_activators_zone,
                              zone_tags_i=chan.channel_inhibitors_zone)

    # if there are any user-defined relations, add them in:

    if self.additional_edges is not None:
        for node_list in self.additional_edges:
            node1, node2, relation = node_list

            if not base_graph.get_node(node1):
                raise BetsePyDotException(
                    'Additional node "{}" not found.'.format(node1))

            if not base_graph.get_node(node2):
                raise BetsePyDotException(
                    'Additional node "{}" not found.'.format(node2))

            if relation == 'activation':
                arrowh = 'dot'
                arrowc = 'blue'

            elif relation == 'inhibition':
                arrowh = 'tee'
                arrowc = 'red'

            else:
                arrowh = 'normal'
                arrowc = 'black'

            base_graph.add_edge(
                pydot.Edge(node1,
                           node2,
                           arrowhead=arrowh,
                           color=arrowc,
                           penwidth=self.edge_width))

    # if sub-graphs are defined, re-jigger the network to have clusters/sub-networks:
    if (self.subnets_dicts is not None and self.subnets_dicts != 'None'
            and len(self.subnets_dicts) > 0):
        base_graph = make_subgraphs(self, base_graph, p)

    return base_graph
Пример #8
0
def _is_parent_command_psutil(command_basename: str) -> bool:
    '''
    ``True`` only if the parent process of the active Python interpreter is
    running an external command with the passed basename, implemented in terms
    of the optional :mod:`psutil` dependency.

    See Also
    ----------
    https://stackoverflow.com/a/2241047/2809027
        StackOverflow answer strongly inspiring this implementation.
    :func:`is_parent_command`
        Further details.
    '''

    # Avoid circular import dependencies.
    from betse.lib import libs
    from betse.util.os.brand import windows
    from betse.util.path import pathnames

    # Optional "psutil" dependency.
    psutil = libs.import_runtime_optional('psutil')

    # Object encapsulating the current process.
    current_proc = psutil.Process()

    # Object encapsulating the parent process of this process if any *OR*
    # "None" otherwise.
    parent_proc = current_proc.parent()

    # If the current process has *NO* parent process, raise an exception.
    #
    # In theory, all processes except the initial "init" process should
    # *ALWAYS* have a parent process on POSIX-compatible platforms. In
    # practice, "psutil" documentation explicitly states that the
    # psutil.Process.parent() method returns "None" in edge cases. *sigh*
    if parent_proc is None:
        raise BetseProcessNotFoundException(
            'Current process {} parent not found.'.format(current_proc))
    # Else, the current process has a parent process.

    # If...
    if (
        # The current platform is Windows *AND*...
        windows.is_windows() and
        # This command basename is *NOT* suffixed by a filetype...
        not pathnames.is_filetype(command_basename)
    # Then suffix this basename by ".exe". This is required, as Windows
    # executables are *ALWAYS* suffixed by such a filetype.
    ):
        command_basename += '.exe'

    # Attempt to...
    try:
        # Dictionary of all metadata required to implement this tester.
        #
        # Note that this call:
        #
        # * Efficiently retrieves this metadata with one method call rather
        #   than inefficiently distributing this retrieval across multiple
        #   method calls.
        # * Transparently sets the values of all metadata whose retrieval
        #   raises an "AccessDenied" or "ZombieProcess" exception to "None."
        #   Sadly, the "NoSuchProcess" exception is *NOT* handled similarly and
        #   *MUST* thus be explicitly caught below.
        parent_proc_metadata = parent_proc.as_dict(
            attrs=('name', 'exe', 'cmdline'))

        # List of one or more strings comprising the command line invoking
        # this parent process *OR* "None" if retrieving this metadata
        # raised an exception above.
        parent_proc_cmdline = parent_proc_metadata['cmdline']

        # If either...
        return (
            # This command basename is this parent process' name *OR*...
            #
            # Note that this metadata typically requires the least privelages
            # on most platforms *AND* is typically the most efficient such
            # metadata to access. So, this metadata is tested first.
            command_basename == parent_proc_metadata['name'] or
            # This command basename is that of this parent process *OR*...
            command_basename == pathnames.get_basename(
                parent_proc_metadata['exe']) or
            (
                # This parent process' command line was retrievable *AND*...
                parent_proc_cmdline and
                # This command basename is that of the first item of this line.
                command_basename == pathnames.get_basename(
                    parent_proc_cmdline[0])
            )
        )
    # If this parent process died during metadata access, raise an exception.
    except psutil.NoSuchProcess as exception:
        raise BetseProcessNotFoundException(
            'Current process {} parent {} killed.'.format(
                current_proc, parent_proc)
        ) from exception