#!/usr/bin/env python# -*- coding: utf-8 -*-## This file is part of the `pypath` python module## Copyright 2014-2023# EMBL, EMBL-EBI, Uniklinik RWTH Aachen, Heidelberg University## Authors: see the file `README.rst`# Contact: Dénes Türei (turei.denes@gmail.com)## Distributed under the GPLv3 License.# See accompanying file LICENSE.txt or copy at# https://www.gnu.org/licenses/gpl-3.0.html## Website: https://pypath.omnipathdb.org/#importcollectionstry:importcollections.abcascollections_abcexcept:importcollectionsascollections_abcimportpypath.share.settingsassettingsimportpypath.share.commonascommonimportpypath.core.entityasentityAnnotDefKey=collections.namedtuple('AnnotDefKey',['name','parent','resource',],)
[docs]classAnnotDef(collections.namedtuple('AnnotDefBase',['name','resource','parent','aspect','scope','source','args','exclude','transmitter','receiver','resource_name','limit','avoid','enabled',])):""" Annotations are defined by a ``name``, a ``resource`` and an ``args`` parameter. If the former is a string it will be first looked up among the annotation resources in ``pypath.annot.db``. Otherwise among the keys of the classes in the ``CustomAnnotation`` object or in the dictionary of the class_definitions. If ``source`` is a `set`, it will be used as a category without further processing. If it is callable it will be called and should return a `set`. If ``bool(args)`` is `False`, in case of annotations in ``pypath.annot.db`` the ``to_set`` method will be called. Otherwise ``args`` will be passed to the ``get_subset`` method. If ``resource`` is callable, ``args`` will be passed if available. """def__new__(cls,name,resource,parent=None,aspect='functional',scope='specific',source='resource_specific',args=None,exclude=None,transmitter=None,receiver=None,resource_name=None,limit=None,avoid=None,enabled=True,):resource_name=(resourceifcls._is_resource_name(resource)else(resource_nameorsettings.get('annot_composite_database_name')or'Unknown'))returnsuper().__new__(cls,name=name,resource=resource,parent=parentorname,aspect=aspect,scope=scope,source=source,args=args,exclude=exclude,transmitter=transmitter,receiver=receiver,resource_name=resource_name,limit=cls._zero_one_or_more(limit),avoid=cls._zero_one_or_more(avoid),enabled=enabled,)@propertydefkey(self):returnAnnotDefKey(name=self.name,parent=self.parent,resource=self.resource_name,)@staticmethoddef_is_resource_name(name):return(isinstance(name,str)andnot(name.startswith('~')orname.startswith('#')))@staticmethoddef_zero_one_or_more(arg):return(()ifnotargelse(arg,)ifisinstance(arg,(str,_annot_type))elsearg)
[docs]classAnnotOp(collections.namedtuple('AnnotOpBase',['annots','op'],)):""" Annotation operations consist of list of annotation definitions or names as they can be looked up in the ``class_definitions`` of the ``CustomAnnotation`` object and an operator to be called on the sets (union, intersection or difference). """def__new__(cls,annots,op=set.union):ifopinAnnotationGroup._set_methods:op=getattr(AnnotationGroup,op.__name__)returnsuper().__new__(cls,annots,op)
[docs]classAnnotationGroup(collections_abc.Set):""" Represents a set of molecular entities sharing a custom defined annotation. This class behaves like a ``set`` and set operations on it result set objects. Normally this class is instantiated by ``pypath.core.annot.CustomAnnotation`` in the process of populating categories and the contents of the groups defined in ``pypath.core.intercell_annot`` in case of annotations of the intercellular communication roles. For detailed definitions of the parameter values see the Supplementary Table S10 in Turei et al. 2020 (in prep). :param list,set,tuple members: The identifiers of the entities in the category. :param str name: The name of the category. :param str parent: The name of the parent category; might be the same as ``name`` in case of high level (generic) categories. :param str aspect: Either *functional* or *locational*. :param str source: Either *resource_specific* or *composite*. :param str scope: Either *specific* or *generic*. :param str resource: The resource (database) name; in case of composite categories it should be the name of the database you are actually building, this by default is `OmniPath` and you can change by the ``pypath.share.settings`` module using the ``annot_composite_database_name`` key. :param bool transmitter: Whether the category contains transmitters of signaling information from the cell expressing the molecular entities in direction of other cells. :param bool receiver: Whether the category contains receivers of signaling information from other cells in direction of the cells expressing the molecular entites in the category. :param str,set limit: Limit to this or these categories. E.g. if it's 'extracellular' the result will be the intersection of this category and 'extracellular' i.e. the category will be limited to extracellular proteins. :param str,set avoid: Avoid elements of this or these categories. E.g. if it's 'cell_surface' then all cell_surface proteins will be removed from this category. """_set_methods={set.union,set.intersection,set.difference,set.symmetric_difference,}
def__iter__(self):returnself.members.__iter__()def__contains__(self,other):returnotherinself.membersdef__len__(self):returnlen(self.members)@classmethoddef_from_iterable(cls,iterable):returnset(iterable)def__repr__(self):return'<AnnotationGroup `%s` from %s, %u elements>'%(self.name,self.resource,len(self),)@propertydeflabel(self):return'%s%s@%s'%(self.parent,'::%s'%self.nameifself.name!=self.parentelse'',self.resource)@propertydefname_label(self):returncommon.upper0(self.name).replace('_',' ')@propertydefkey(self):returnAnnotDefKey(name=self.name,parent=self.parent,resource=self.resource,)
[docs]deffilter_entity_type(self,entity_type=None):""" Returns a copy of the group with only the selected entity types. If ``entity_type`` is None returns the object itself. """ifentity_typeisNone:returnselfelse:members=entity.Entity.filter_entity_type(self.members,entity_type=entity_type,)returnAnnotationGroup(members=members,name=self.name,parent=self.parent,aspect=self.aspect,source=self.source,scope=self.scope,resource=self.resource,transmitter=self.transmitter,receiver=self.transmitter,)