Skip to content

Commit

Permalink
Move Relationship classproperties to classmethods
Browse files Browse the repository at this point in the history
  • Loading branch information
Martin Larralde committed Jul 16, 2016
1 parent 9eeba3a commit f2d90b7
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 81 deletions.
59 changes: 28 additions & 31 deletions pronto/ontology.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@


class Ontology(object):
"""The base class for an ontology.
"""An ontology.
Ontologies inheriting from this class will be able to use the same API as
providing they generated the expected structure in the :func:`_parse`
Expand Down Expand Up @@ -202,8 +202,7 @@ def include(self, *terms):
"""Add new terms to the current ontology.
Raises:
TypeError: when the object(s) passed to the function is (are)
not either a TermList or a Term.
TypeError: when the arguments is (are) neither a TermList nor a Term.
Note:
This will also recursively include terms in the term's relations
Expand All @@ -212,23 +211,22 @@ def include(self, *terms):
as 'ONT:001') to your terms relations, and let the Ontology link
terms with each other.
:Example:
Examples:
Create a new ontology from scratch
Create a new ontology from scratch:
>>> from pronto import Term, Relationship
>>> t1 = Term('ONT:001','my 1st term',
... 'this is my first term')
>>> t2 = Term('ONT:002', 'my 2nd term',
... 'this is my second term',
... {Relationship('part_of'): ['ONT:001']})
>>> ont = Ontology()
>>> ont.include(t1, t2)
>>> from pronto import Term, Relationship
>>> t1 = Term('ONT:001','my 1st term',
... 'this is my first term')
>>> t2 = Term('ONT:002', 'my 2nd term',
... 'this is my second term',
... {Relationship('part_of'): ['ONT:001']})
>>> ont = Ontology()
>>> ont.include(t1, t2)
>>> 'ONT:002' in ont
True
>>> ont['ONT:001'].children
[<ONT:002: my 2nd term>]
>>> 'ONT:002' in ont
True
>>> ont['ONT:001'].children
[<ONT:002: my 2nd term>]
"""
ref_needed = False
Expand Down Expand Up @@ -302,19 +300,18 @@ def _include_term(self, term):
def merge(self, other):
"""Merges another ontology into the current one.
:Example:
>>> from pronto import Ontology
>>> nmr = Ontology('http://nmrml.org/cv/v1.0.rc1/nmrCV.owl', False)
>>> po = Ontology('https://raw.githubusercontent.com/Planteome'
... '/plant-ontology/master/po.obo', False)
>>> 'NMR:1000271' in nmr
True
>>> 'NMR:1000271' in po
False
>>> po.merge(nmr)
>>> 'NMR:1000271' in po
True
Example:
>>> from pronto import Ontology
>>> nmr = Ontology('http://nmrml.org/cv/v1.0.rc1/nmrCV.owl', False)
>>> po = Ontology('https://raw.githubusercontent.com/Planteome'
... '/plant-ontology/master/po.obo', False)
>>> 'NMR:1000271' in nmr
True
>>> 'NMR:1000271' in po
False
>>> po.merge(nmr)
>>> 'NMR:1000271' in po
True
"""
if isinstance(other, Ontology):
Expand Down
30 changes: 18 additions & 12 deletions pronto/relationship.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import multiprocessing
import threading
import functools
import collections

import pronto.utils
Expand Down Expand Up @@ -45,8 +46,8 @@ def __init__(self, obo_name, symmetry=None, transitivity=None,
this Relationship obo_name
.. note::
For :param:`symetry`, :param:`transitivity`, :param:`reflexivity`,
the allowed values are the following:
For :symetry, transitivity, reflexivity, the allowed values are
the following:
- True for reflexive, transitive, symmetric
- False for areflexive, atransitive, asymmetric
- None for non-reflexive, non-transitive, non-symmetric
Expand Down Expand Up @@ -98,10 +99,11 @@ def complement(self):
return None

def __repr__(self):
"""Overloaded :obj:`object.__repr__`"""
return "Relationship({})".format(self.obo_name)

def __new__(cls, obo_name, *args, **kwargs):
"""Overloaded py:method::__new__ method that _memoizes_ the objects.
"""Overloaded :obj:`object.__new__` method that __memoizes__ the objects.
This allows to do the following (which is frecking cool):
Expand All @@ -124,35 +126,39 @@ def __new__(cls, obo_name, *args, **kwargs):
else:
return super(Relationship, cls).__new__(cls)

@pronto.utils.classproperty
def topdown(self):
"""An iterator over all "topdown" direction Relationships object
#@pronto.utils.classproperty
@classmethod
def topdown(cls):
"""Get all topdown Relationship instances
Returns:
:obj:`generator`
Example:
>>> from pronto import Relationship
>>> for r in Relationship.topdown:
>>> for r in Relationship.topdown():
... print(r)
Relationship(can_be)
Relationship(has_part)
"""
return (r for r in self._instances.values() if r.direction=='topdown')
return (r for r in cls._instances.values() if r.direction=='topdown')

@pronto.utils.classproperty
#@pronto.utils.classproperty
@classmethod
def bottomup(self):
"""An iterator over all "bottomup" direction Relationships object
"""Get all bottomup Relationship instances
Example:
>>> from pronto import Relationship
>>> for r in Relationship.bottomup:
>>> for r in Relationship.bottomup():
... print(r)
Relationship(is_a)
Relationship(part_of)
"""

return pronto.utils.unique_everseen(r for r in self._instances.values() if r.direction=='bottomup')

@pronto.utils.classproperty
Expand Down
70 changes: 38 additions & 32 deletions pronto/term.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,28 @@

class Term(object):
""" An ontology term.
Example:
>>> from pronto import Term, Relationship
>>> new_term = Term('TR:001', 'new term', 'a new term')
>>> linked_term = Term('TR:002', 'other new', 'another term',
... { Relationship('is_a'): 'TR:001'})
"""

def __init__(self, tid, name, desc='', relations=None, other=None):
"""Instantiate a new term.
"""
Parameters
Parameters:
tid (str): the Term id (e.g. MS:1000031)
name (str): the name of the Term in human language
desc (str): a description of the Term
relations (dict): a dictionary containing the other
terms the Term is in a relationship with.
other (dict): other information about the term
Example
>>> from pronto import Term, Relationship
>>> new_term = Term('TR:001', 'new term', 'a new term')
>>> linked_term = Term('TR:002', 'other new', 'another term',
... { Relationship('is_a'): 'TR:001'})
"""
self.id = tid
self.name = name
Expand All @@ -48,17 +49,18 @@ def __repr__(self):
def parents(self):
"""The parents of the Term.
Returns
parents (pronto.term.TermList): a TermList containing all parents
of the Term (other terms with which this Term has a "bottomup"
relationship)
Returns:
:obj:`pronto.TermList`:
a TermList containing all parents of the Term
(other terms with which this Term has a "bottomup"
relationship)
"""

if self._parents is not None:
return self._parents
else:
self._parents = TermList()
for rship in Relationship.bottomup:
for rship in Relationship.bottomup():
if rship in self.relations.keys():
self._parents.extend(self.relations[rship])
return self._parents
Expand All @@ -67,16 +69,18 @@ def parents(self):
def children(self):
"""The children of the Term.
Returns
children (pronto.term.TermList): a TermList containing all parents
of the Term (other terms with which this Term has a "topdown"
relationship)
Returns:
:obj:`pronto.TermList`:
a TermList containing all parents of the Term
(other terms with which this Term has a "topdown"
relationship)
"""
if self._children is not None:
return self._children
else:
self._children = TermList()
for rship in Relationship.topdown:
for rship in Relationship.topdown():
if rship in self.relations.keys():
self._children.extend(self.relations[rship])
return self._children
Expand All @@ -101,7 +105,7 @@ def obo(self):

# add relationships (only bottom up ones)

for relation in Relationship.bottomup:
for relation in Relationship.bottomup():
try:
for companion in self.relations[relation]:

Expand Down Expand Up @@ -146,15 +150,15 @@ def rchildren(self, level=-1, intermediate=True):
Note that the :param:`intermediate` can be used to include every
child to the returned list, not only the most nested ones.
Parameters
Parameters:
level (int): The depth level to continue fetching children from
(default is -1, to get children to the utter depths)
intermediate (bool): Also include the intermediate children
(default is True)
Returns
rchildren (pronto.term.TermList): The recursive children
of the Term following the parameters
Returns:
:obj:`pronto.TermList`:
The recursive children of the Term following the parameters
"""
try:
Expand Down Expand Up @@ -183,15 +187,15 @@ def rparents(self, level=-1, intermediate=True):
Note that the :param:`intermediate` can be used to include every
parents to the returned list, not only the most nested ones.
Parameters
Parameters:
level (int): The depth level to continue fetching parents from
(default is -1, to get parents to the utter depths)
intermediate (bool): Also include the intermediate parents
(default is True)
Returns
rchildren (pronto.term.TermList): The recursive children
of the Term following the parameters
Returns:
:obj:`pronto.TermList`:
The recursive children of the Term following the parameters
"""
try:
Expand Down Expand Up @@ -222,7 +226,6 @@ class TermList(list):
generate lists of terms' attributes.
Example:
>>> from pronto import Ontology, Relationship
>>> nmr = Ontology('http://nmrml.org/cv/v1.0.rc1/nmrCV.owl')
>>> type(nmr['NMR:1000031'].children)
Expand All @@ -234,7 +237,7 @@ class TermList(list):
[<NMR:1400011: cardinal part of NMR instrument>]
.. note::
.. tip::
It is also possible to call Term methods on a TermList to
create a set of terms::
Expand All @@ -244,6 +247,8 @@ class TermList(list):
"""

def __init__(self, *elements):
"""
"""
list.__init__(self, *elements)
self._check_content()

Expand Down Expand Up @@ -272,7 +277,8 @@ def mapped(level=-1, intermediate=True):

def __contains__(self, term):
"""
Todo: write doc & test
Todo:
write doc & test
"""
return term in self.id or any(t for t in self if t==term)

Expand Down
Loading

0 comments on commit f2d90b7

Please sign in to comment.