Changeset 1733:548d1187a29f in orange-bioinformatics


Ignore:
Timestamp:
03/05/13 19:48:00 (14 months ago)
Author:
Ales Erjavec <ales.erjavec@…>
Branch:
default
Message:

Porting obiKEGG to use the new REST KEGG API.

Files:
10 edited

Legend:

Unmodified
Added
Removed
  • _bioinformatics/obiKEGG/__init__.py

    r1716 r1733  
    44============================================== 
    55 
    6 This is a python module for access to `KEGG`_ using its web services. To use this module you need to have 
    7 `SUDS`_ python library installed (other backends are planed).  
     6This is a python module for access to `KEGG`_ using its web services. 
     7 
     8To use this module you need to have `slumber` and `requests` package 
     9installed. 
    810 
    911.. _`KEGG`: http://www.genome.jp/kegg/ 
    1012 
    11 .. _`SUDS`: http://pypi.python.org/pypi/suds/ 
    1213 
    1314""" 
    1415from __future__ import absolute_import 
    1516 
     17import os 
     18import sys 
    1619import urllib2 
    17 import os, sys 
     20 
    1821from collections import defaultdict 
    1922 
     
    2124 
    2225from Orange.utils import lru_cache 
     26from Orange.utils import progress_bar_milestones 
     27from Orange.utils import deprecated_keywords, deprecated_attribute, \ 
     28                         deprecated_function_name 
     29 
     30from .. import obiProb 
    2331 
    2432from . import databases 
     
    3341KEGGGenome = databases.Genome 
    3442KEGGGenes = databases.Genes 
    35 KEGGEnzymes = databases.Enzymes 
    36 KEGGReaction = databases.Reactions 
    37 KEGGPathways = databases.Pathways 
     43KEGGEnzyme = databases.Enzyme 
     44KEGGReaction = databases.Reaction 
     45KEGGPathways = databases.Pathway 
     46KEGGCompound = databases.Compound 
    3847 
    3948KEGGBrite = Brite 
     
    4554 
    4655 
    47 from .. import obiProb 
    48 from Orange.utils import deprecated_keywords, deprecated_attribute 
    49  
    50 class OrganismNotFoundError(Exception): pass 
     56class OrganismNotFoundError(Exception): 
     57    pass 
     58 
    5159 
    5260class Organism(object): 
     61    """ 
     62    A convenience class for retrieving information regarding an 
     63    organism in the KEGG Genes database. 
     64 
     65    :param org: KEGGG organism code (e.g. "hsa", "sce") 
     66    :type org: str 
     67 
     68    """ 
    5369    def __init__(self, org, genematcher=None): 
    5470        self.org_code = self.organism_name_search(org) 
    5571        self.genematcher = genematcher 
    5672        self.api = api.CachedKeggApi() 
    57          
     73 
    5874    @property 
    5975    def org(self): 
     76        """ 
     77        KEGG organism code. 
     78        """ 
    6079        return self.org_code 
    61      
     80 
    6281    @property 
    6382    def genes(self): 
     83        """ 
     84        An :class:`Genes` database instance for this organism. 
     85        """ 
     86        # TODO: This should not be a property but a method. 
     87        # I think it was only put here as back compatibility with old obiKEGG. 
    6488        if not hasattr(self, "_genes"): 
    6589            genes = KEGGGenes(self.org_code) 
    6690            self._genes = genes 
    6791        return self._genes 
    68      
     92 
    6993    def gene_aliases(self): 
    70         return self.genes().gene_aliases() 
    71      
     94        """ 
     95        Return known gene aliases (synonyms in other databases). 
     96        """ 
     97        return self.genes.gene_aliases() 
     98 
    7299    def pathways(self, with_ids=None): 
     100        """ 
     101        Return a list of all pathways for this organism. 
     102        """ 
    73103        if with_ids is not None: 
    74104            return self.api.get_pathways_by_genes(with_ids) 
     
    77107     
    78108    def list_pathways(self): 
     109        """ 
     110        List all pathways. 
     111        """ 
     112        # NOTE: remove/deprecate and use pathways() 
    79113        return self.pathways() 
    80114     
     
    97131                tabs = l.split("\t") 
    98132                cset = set([tabs[0]]) 
     133 
     134                if ":" in tabs[0]: 
     135                    # also add 'identifier' from 'org_code:identifier' 
     136                    cset.add(tabs[0].split(":", 1)[-1]) 
     137 
    99138                try: 
    100139                    rest = tabs[1].split(";")[0] 
    101140                    cset |= set(rest.split(", ")) 
    102141                except: 
    103                     pass #do not crash if a line does not conform 
     142                    pass  # do not crash if a line does not conform 
    104143                out.append(cset) 
    105144        return out 
    106145 
    107     def get_enriched_pathways(self, genes, reference=None, prob=obiProb.Binomial(), callback=None): 
    108         """ Return a dictionary with enriched pathways ids as keys 
    109         and (list_of_genes, p_value, num_of_reference_genes) tuples  
     146    def get_enriched_pathways(self, genes, reference=None, 
     147                              prob=obiProb.Binomial(), callback=None): 
     148        """ 
     149        Return a dictionary with enriched pathways ids as keys 
     150        and (list_of_genes, p_value, num_of_reference_genes) tuples 
    110151        as items. 
    111          
    112         """ 
    113         allPathways = defaultdict(lambda :[[], 1.0, []]) 
    114         from Orange.orng import orngMisc 
    115         milestones = orngMisc.progressBarMilestones(len(genes), 100) 
     152 
     153        """ 
     154        if reference is None: 
     155            reference = self.genes.keys() 
     156        reference = set(reference) 
     157 
     158        allPathways = defaultdict(lambda: [[], 1.0, []]) 
     159        milestones = progress_bar_milestones(len(genes), 100) 
    116160        pathways_db = KEGGPathways() 
    117          
     161 
    118162        pathways_for_gene = [] 
    119163        for i, gene in enumerate(genes): 
    120164            pathways_for_gene.append(self.pathways([gene])) 
    121165            if callback and i in milestones: 
    122                 callback(i*50.0/len(genes)) 
    123                  
    124         # precache for speed  
    125         pathways_db.pre_cache([pid for pfg in pathways_for_gene for pid in pfg])  
     166                callback(i * 50.0 / len(genes)) 
     167 
     168        # pre-cache for speed 
     169        pathways_db.pre_cache([pid for pfg in pathways_for_gene 
     170                               for pid in pfg]) 
    126171        for i, (gene, pathways) in enumerate(zip(genes, pathways_for_gene)): 
    127172            for pathway in pathways: 
    128                 if pathways_db.get_entry(pathway).gene:  
     173                if pathways_db.get_entry(pathway).gene: 
    129174                    allPathways[pathway][0].append(gene) 
    130175            if callback and i in milestones: 
    131                 callback(50.0 + i*50.0/len(genes)) 
    132         reference = set(reference if reference is not None else self.genes.keys()) 
    133          
     176                callback(50.0 + i * 50.0 / len(genes)) 
     177 
    134178        pItems = allPathways.items() 
    135          
     179 
    136180        for i, (p_id, entry) in enumerate(pItems): 
    137181            pathway = pathways_db.get_entry(p_id) 
    138182            entry[2].extend(reference.intersection(pathway.gene or [])) 
    139             entry[1] = prob.p_value(len(entry[0]), len(reference), len(entry[2]), len(genes)) 
    140         return dict([(pid, (genes, p, len(ref))) for pid, (genes, p, ref) in allPathways.items()]) 
    141          
     183            entry[1] = prob.p_value(len(entry[0]), len(reference), 
     184                                    len(entry[2]), len(genes)) 
     185        return dict([(pid, (genes, p, len(ref))) 
     186                     for pid, (genes, p, ref) in allPathways.items()]) 
     187 
    142188    def get_genes_by_enzyme(self, enzyme): 
    143         enzyme = Enzymes().get_entry(enzyme) 
     189        enzyme = KEGGEnzyme().get_entry(enzyme) 
    144190        return enzyme.genes.get(self.org_code, []) if enzyme.genes else [] 
    145      
     191 
    146192    def get_genes_by_pathway(self, pathway_id): 
    147193        return KEGGPathway(pathway_id).genes() 
    148      
     194 
    149195    def get_enzymes_by_pathway(self, pathway_id): 
    150196        return KEGGPathway(pathway_id).enzymes() 
     
    156202        return self.api.get_pathways_by_genes(gene_ids) 
    157203        gene_ids = set(gene_ids) 
    158         pathways = [self.genes[id].pathway for id in gene_ids if self.genes[id].pathway] 
     204        pathways = [self.genes[id].pathway for id in gene_ids 
     205                    if self.genes[id].pathway] 
    159206        pathways = reduce(set.union, pathways, set()) 
    160         return [id for id in pathways if gene_ids.issubset(KEGGPathway(id).genes())]  
    161      
     207        return [id for id in pathways 
     208                if gene_ids.issubset(KEGGPathway(id).genes())] 
     209 
    162210    def get_pathways_by_enzymes(self, enzyme_ids): 
    163211        enzyme_ids = set(enzyme_ids) 
    164         pathways = [KEGGEnzymes()[id].pathway for id in enzyme_ids] 
    165         pathwats = reduce(set.union, pathways, set()) 
    166         return [id for id in pathways if enzyme_ids.issubset(KEGGPathway(id).enzymes())] 
    167      
     212        pathways = [KEGGEnzyme()[id].pathway for id in enzyme_ids] 
     213        pathways = reduce(set.union, pathways, set()) 
     214        return [id for id in pathways 
     215                if enzyme_ids.issubset(KEGGPathway(id).enzymes())] 
     216 
    168217    def get_pathways_by_compounds(self, compound_ids): 
    169218        compound_ids = set(compound_ids) 
    170         pathways = [KEGGCompounds()[id].pathway for id in compound_ids] 
    171         pathwats = reduce(set.union, pathways, set()) 
    172         return [id for id in pathways if compound_ids.issubset(KEGGPathway(id).compounds())] 
    173      
     219        pathways = [KEGGCompound()[id].pathway for id in compound_ids] 
     220        pathways = reduce(set.union, pathways, set()) 
     221        return [id for id in pathways 
     222                if compound_ids.issubset(KEGGPathway(id).compounds())] 
     223 
    174224    def get_enzymes_by_compound(self, compound_id): 
    175225        return KEGGCompound()[compound_id].enzyme 
    176      
     226 
    177227    def get_enzymes_by_gene(self, gene_id): 
    178228        return self.genes[gene_id].enzymes 
    179      
     229 
    180230    def get_compounds_by_enzyme(self, enzyme_id): 
    181231        return self._enzymes_to_compounds.get(enzyme_id) 
     
    183233    @deprecated_keywords({"caseSensitive": "case_sensitive"}) 
    184234    def get_unique_gene_ids(self, genes, case_sensitive=True): 
    185         """Return a tuple with three elements. The first is a dictionary mapping from unique gene 
    186         ids to gene names in genes, the second is a list of conflicting gene names and the third is a list 
    187         of unknown genes. 
     235        """ 
     236        Return a tuple with three elements. The first is a dictionary 
     237        mapping from unique geneids to gene names in genes, the second 
     238        is a list of conflicting gene names and the third is a list of 
     239        unknown genes. 
     240 
    188241        """ 
    189242        unique, conflicting, unknown = {}, [], [] 
     
    197250                conflicting.append(gene) 
    198251        return unique, conflicting, unknown 
    199      
     252 
     253    @deprecated_function_name 
    200254    def get_genes(self): 
    201255        return self.genes 
    202      
     256 
    203257    @classmethod 
    204258    def organism_name_search(cls, name): 
     
    213267             
    214268        try: 
    215             return genome[name].entry_key 
     269            return genome[name].organism_code 
    216270        except KeyError: 
    217271            raise OrganismNotFoundError(name) 
     
    221275        name = cls.organism_name_search(name) 
    222276        genome = KEGGGenome() 
    223         info = genome.api.binfo(name) 
     277        info = genome.api.info(name) 
    224278        return info.release 
    225      
     279 
    226280    def _set_genematcher(self, genematcher): 
    227281        setattr(self, "_genematcher", genematcher) 
     
    231285            from .. import obiGene 
    232286            if self.org_code == "ddi": 
    233                 self._genematcher = obiGene.matcher([obiGene.GMKEGG(self.org_code), obiGene.GMDicty(), 
    234                                                      [obiGene.GMKEGG(self.org_code), obiGene.GMDicty()]]) 
     287                self._genematcher = obiGene.matcher( 
     288                    [obiGene.GMKEGG(self.org_code), obiGene.GMDicty(), 
     289                    [obiGene.GMKEGG(self.org_code), obiGene.GMDicty()]] 
     290                ) 
    235291            else: 
    236                 self._genematcher = obiGene.matcher([obiGene.GMKEGG(self.org_code)]) 
     292                self._genematcher = obiGene.matcher( 
     293                    [obiGene.GMKEGG(self.org_code)]) 
     294 
    237295            self._genematcher.set_targets(self.genes.keys()) 
    238296        return self._genematcher 
    239297     
    240298    genematcher = property(_get_genematcher, _set_genematcher) 
    241      
     299 
     300 
    242301KEGGOrganism = Organism 
    243      
     302 
     303 
    244304def organism_name_search(name): 
    245305    return KEGGOrganism.organism_name_search(name) 
     
    259319        if e.taxid in [taxid,  genome.TAXID_MAP.get(taxid, taxid)]: 
    260320            return e.org_code() 
    261          
     321 
    262322    return None 
    263323 
     
    266326    if name in genome: 
    267327        return genome[name].taxid 
    268      
     328 
    269329    keys = genome.search(name) 
    270330    if keys: 
     
    276336    pass 
    277337 
     338 
    278339def main(): 
    279340    KEGGGenome() 
     
    282343    doctest.testmod(optionflags=doctest.ELLIPSIS, extraglobs=extraglobs) 
    283344 
     345 
    284346if __name__ == "__main__": 
    285347    sys.exit(main()) 
  • _bioinformatics/obiKEGG/api.py

    r1716 r1733  
    55from __future__ import absolute_import 
    66 
     7from datetime import datetime 
    78from contextlib import closing 
     9from operator import itemgetter 
     10import warnings 
    811 
    912from .service import web_service 
    10 from .types import * 
     13from .types import OrganismSummary, Definition, BInfo, Link 
     14 
     15 
     16DATABASES = [ 
     17    ("KEGG Pathway", "pathway", "path", None), 
     18    ("KEGG Brite", "brite", "br", None), 
     19    ("KEGG Module", "module", "md", "M"), 
     20    ("KEGG Disease", "disease", "ds", "H"), 
     21    ("KEGG Drug", "drug", "dr", "D"), 
     22    ("KEGG Orthology", "orthology", "ko", "K"), 
     23    ("KEGG Genome", "genome", "genome", "T"), 
     24    ("KEGG Genomes", "genomes", "gn", "T"), 
     25    ("KEGG Genes", "genes", None, None), 
     26    ("KEGG Ligand", "ligand", "ligand", None), 
     27    ("KEGG Compound", "compound", "cpd", "C"), 
     28    ("KEGG Glycan", "glycan", "gl", "G"), 
     29    ("KEGG Reaction", "reaction", "rn", "R"), 
     30    ("KEGG RPair", "rpair", "rp", "RP"), 
     31    ("KEGG RClass", "rclass", "rc", "RC"), 
     32    ("KEGG Enzyme", "enzyme", "ec", "E") 
     33] 
     34 
     35 
     36def _link_targets(links): 
     37    return sorted(set(map(itemgetter(1), links))) 
     38 
    1139 
    1240class KeggApi(object): 
    13     """ KEGG API """ 
    14      
     41    """ 
     42    An abstraction of a kegg api. 
     43    """ 
     44 
    1545    def __init__(self): 
    1646        self.service = web_service() 
    17          
    18     ################## 
    19     # Meta information 
    20     ################## 
    21      
    22     def list_databases(self): 
    23         """ Returns a list of available databases. 
    24          
    25         >>> api.list_databases() 
    26         [Definition(entry_id='nt',... 
    27           
    28         """ 
    29         return map(Definition.from_items, self.service.list_databases()) 
    30      
     47 
    3148    def list_organisms(self): 
    32         """ Return a list of all available organisms 
    33          
     49        """ 
     50        Return a list of all available organisms 
     51 
    3452        >>> api.list_organisms() 
    3553        [Definition(entry_id='hsa',... 
    36          
    37         """ 
    38         return map(Definition.from_items, self.service.list_organisms()) 
    39      
     54 
     55        """ 
     56        return map(OrganismSummary.from_str, 
     57                   self.service.list.organism.get().splitlines()) 
     58 
    4059    def list_pathways(self, organism): 
    41         """ Return a list of all available pathways for `organism` 
    42          
     60        """ 
     61        Return a list of all available pathways for `organism` 
     62 
    4363        >>> api.list_pathways("hsa") 
    4464        [Definition(entry_id=',... 
    45          
    46         """ 
    47         return map(Definition.from_items, self.service.list_pathways(organism)) 
    48          
     65 
     66        """ 
     67        return map(Definition.from_str, 
     68                   self.service.list.pathway(organism).get().splitlines()) 
     69 
     70    def list(self, db): 
     71        """ 
     72        Return a list of all available entries in database `db`. 
     73        """ 
     74        return map(Definition.from_str, 
     75                   self.service.list(db).get().splitlines()) 
     76 
    4977    ####### 
    5078    # DBGET 
    5179    ####### 
    52       
    53     def binfo(self, db): 
    54         """ Return info for database `db` 
    55          
    56         >>> print api.dbinfo("gb") 
    57         genbank          GenBank nucleic acid sequence database 
    58         gb               Release 186.0, Oct 11 
    59                          National Center for Biotechnology Information 
    60                          144,458,648 entries, 132,067,413,372 bases 
    61                          Last update: 11/10/24 
    62                          <dbget> <fasta> <blast> 
    63                           
    64         """ 
    65         result = self.service.binfo(db) 
    66         if result is not None: 
    67             return BInfo.from_text(str(result)) 
    68         else: 
    69             return result 
    70      
    71     def bfind(self, db, keywords): 
    72         """ Search database 'db' for keywords 
    73         """ 
    74         result = self.service.bfind(" ".join([db, keywords])) 
    75         if result is not None: 
    76             return str(result) 
    77         else: 
    78             return result 
    79      
    80     def bget(self, ids): 
    81         """ 
     80 
     81    def info(self, db): 
     82        """ 
     83        Return info for database `db` 
     84 
     85        >>> print api.info("pathway") 
     86        BInfo(entry_id='path', definition='KEGG Pathway Database', ... 
     87 
     88        """ 
     89        result = self.service.info(db).get() 
     90        return BInfo.from_text(str(result)) 
     91 
     92    def find(self, db, keywords): 
     93        """ 
     94        Search database 'db' for keywords. 
     95        """ 
     96        if isinstance(keywords, basestring): 
     97            keywords = [keywords] 
     98 
     99        return self.service.find(db)("+".join(keywords)).get() 
     100 
     101    def get(self, ids): 
     102        """ 
     103        Retrieve database entries for `ids` list. 
    82104        """ 
    83105        if not isinstance(ids, basestring): 
    84106            # Sequence of ids 
    85             ids = " ".join(ids) 
    86         result = self.service.bget(ids) 
    87         if result is not None: 
    88             return str(result) 
     107            ids = "+".join(ids) 
     108 
     109        return self.service.get(ids).get() 
     110 
     111    def conv(self, ids): 
     112        raise NotImplementedError() 
     113 
     114    def link(self, target_db, source_db=None, ids=None): 
     115        if not (source_db or ids): 
     116            raise ValueError("One of 'source_db' or 'ids' must be supplied") 
     117        if source_db and ids: 
     118            raise ValueError("Only one 'source_db' or 'ids' must be supplied") 
     119 
     120        if source_db: 
     121            result = self.service.link(target_db)(source_db).get() 
    89122        else: 
    90             return result 
    91      
    92     def btit(self, ids): 
    93         """ 
    94         """ 
    95         if not isinstance(ids, basestring): 
    96             ids = " ".join(ids) 
    97              
    98         result = self.service.btit(ids) 
    99         if result is not None: 
    100             return str(result) 
    101         else: 
    102             return result 
    103      
    104     def bconv(self, ids): 
    105         if not isinstance(ids, basestring): 
    106             ids = " ".join(ids) 
    107              
    108         result = self.service.bconv(ids) 
    109         if result is not None: 
    110             return str(result) 
    111         else: 
    112             return result 
    113      
    114     ######## 
    115     # LinkDB 
    116     ######## 
    117      
    118     def get_linkdb_by_entry(self, entry_id, db, offset, limit): 
    119         links = self.service.get_linkdb_by_entry(entry_id, db, offset, limit) 
    120         return [LinkDBRelation(**d) for d in \ 
    121                 map(dict, links)] 
    122          
    123     def get_linkdb_between_databases(self, from_db, to_db, offset, limit): 
    124         links = self.service.get_linkdb_between_databases(from_db, to_db, offset, limit) 
    125         return [LinkDBRelation(**d) for d in \ 
    126                 map(dict, links)] 
    127          
     123            result = self.service.link(target_db)("+".join(ids)).get() 
     124 
     125        return map(Link._make, map(str.split, result.splitlines())) 
     126 
    128127    def get_genes_by_enzyme(self, enzyme_id, org): 
    129         return self.service.get_genes_by_enzyme(enzyme_id, org) 
    130      
    131     def get_enzymes_by_gene(self, genes_id): 
    132         return self.service.get_enzymes_by_gene(genes_id) 
    133      
     128        return _link_targets(self.link(org, ids=[enzyme_id])) 
     129 
     130    def get_enzymes_by_gene(self, gene_id): 
     131        return _link_targets(self.link("ec", ids=[gene_id])) 
     132 
    134133    def get_enzymes_by_compound(self, compound_id): 
    135         return self.service.get_enzymes_by_compound(compound_id) 
    136      
     134        return _link_targets(self.link("ec", ids=[compound_id])) 
     135 
    137136    def get_enzymes_by_glycan(self, glycan_id): 
    138         return self.service.get_enzymes_by_glycan(glycan_id) 
    139      
     137        return _link_targets(self.link("ec", ids=[glycan_id])) 
     138 
    140139    def get_enzymes_by_reaction(self, reaction_id): 
    141         return self.service.get_enzymes_by_reaction(reaction_id) 
    142      
     140        return _link_targets(self.link("ec", ids=[reaction_id])) 
     141 
    143142    def get_compounds_by_enzyme(self, enzyme_id): 
    144         return self.service.get_compounds_by_enzyme(enzyme_id) 
    145      
     143        return _link_targets(self.link("compound", ids=[enzyme_id])) 
     144 
    146145    def get_compounds_by_reaction(self, reaction_id): 
    147         return self.service.get_compounds_by_reaction(reaction_id) 
    148      
     146        return _link_targets(self.link("compound", ids=[reaction_id])) 
     147 
    149148    def get_glycans_by_enzyme(self, enzyme_id): 
    150         return self.service.get_glycans_by_enzyme(enzyme_id) 
    151      
     149        return _link_targets(self.link("gl", ids=[enzyme_id])) 
     150 
    152151    def get_glycans_by_reaction(self, reaction_id): 
    153         return self.service.get_glycans_by_reaction(reaction_id) 
    154      
     152        return _link_targets(self.link("gl", ids=[reaction_id])) 
     153 
    155154    def get_reactions_by_enzyme(self, enzyme_id): 
    156         return self.service.get_reactions_by_enzyme(enzyme_id) 
    157      
     155        return _link_targets(self.link("rn", ids=[enzyme_id])) 
     156 
    158157    def get_reactions_by_compound(self, compound_id): 
    159         return self.service.get_reactions_by_compound(compound_id) 
    160      
     158        return _link_targets(self.link("rn", ids=[compound_id])) 
     159 
    161160    def get_reactions_by_glycan(self, glycan_id): 
    162         return self.service.get_reactions_by_glycan(glycan_id) 
    163      
     161        return _link_targets(self.link("rn", ids=[glycan_id])) 
     162 
    164163    ###### 
    165164    # SSDB 
    166165    ###### 
    167      
     166 
     167    # No replacement api in the KEGG REST api. 
    168168    def get_best_best_neighbors_by_gene(self, genes_id, offset, limit): 
    169         ssr = self.service.get_best_best_neighbors_by_gene(genes_id, offset, limit) 
    170         return [SSDBRelation(**d) for d in \ 
    171                 map(dict, ssr)] 
    172      
     169        raise NotImplementedError 
     170 
    173171    def get_best_neighbors_by_gene(self, genes_id, offset, limit): 
    174         ssr = self.service.get_best_neighbors_by_gene(genes_id, offset, limit) 
    175         return [SSDBRelation(**d) for d in \ 
    176                 map(dict, ssr)] 
    177      
     172        raise NotImplementedError 
     173 
    178174    def get_reverse_best_neighbors_by_gene(self, genes_id, offset, limit): 
    179         ssr = self.service.get_reverse_best_neighbors_by_gene(genes_id, offset, limit) 
    180         return [SSDBRelation(**d) for d in \ 
    181                 map(dict, ssr)] 
    182      
     175        raise NotImplementedError 
     176 
    183177    def get_paralogs_by_gene(self, genes_id, offset, limit): 
    184         ssr =  self.service.get_paralogs_by_gene(genes_id, offset, limit) 
    185         return [SSDBRelation(**d) for d in \ 
    186                 map(dict, ssr)] 
    187      
     178        raise NotImplementedError 
     179 
    188180    ####### 
    189181    # Motif 
    190182    ####### 
    191      
     183 
     184    # No replacement api in KEGG REST api 
    192185    def get_motifs_by_gene(self, genes_id, db): 
    193         motif = self.service.get_motifs_by_gene(genes_id, db) 
    194         return [MotifResult(**d) for d in \ 
    195                 map(dict, motif)] 
    196      
     186        raise NotImplementedError 
     187 
    197188    def get_genes_by_motifs(self, motif_id_list, offset, limit): 
    198         genes = self.service.get_genes_by_motifs(motif_id_list, offset, limit) 
    199         return [Definition(**d) for d in \ 
    200                 map(dict, genes)] 
    201      
     189        raise NotImplementedError 
     190 
    202191    #### 
    203192    # KO 
    204193    #### 
    205      
     194 
    206195    def get_ko_by_gene(self, genes_id): 
    207         return self.service.get_ko_by_gene(genes_id) 
    208      
     196        raise NotImplementedError 
     197 
    209198    def get_ko_by_ko_class(self, ko_class_id): 
    210         return self.service.get_ko_by_ko_class(ko_class_id) 
    211      
     199        raise NotImplementedError 
     200 
    212201    def get_genes_by_ko_class(self, ko_class_id, org, offset, limit): 
    213         return self.service.get_genes_by_ko_class(ko_class_id, org, offset, limit) 
    214      
     202        raise NotImplementedError 
     203 
    215204    def get_genes_by_ko(self, ko_id, org): 
    216         return self.service.get_genes_by_ko(ko_id, org) 
    217      
     205        raise NotImplementedError 
     206 
    218207    ######### 
    219208    # Pathway 
    220209    ######### 
    221      
     210 
    222211    def mark_pathway_by_objects(self, pathway_id, object_id_list): 
    223         return self.service.mark_pathway_by_objects(pathway_id, object_id_list) 
    224      
    225     def color_pathway_by_objects(self, pathway_id, object_id_list, fg_color_list, bg_color_list): 
    226         return self.service.color_pathway_by_objects(pathway_id, object_id_list, fg_color_list, bg_color_list) 
    227      
    228     def color_pathway_by_elements(self, pathway_id, element_id_list, fg_color_list, bg_color_list): 
    229         return self.service.color_pathway_by_elements(pathway_id, element_id_list, fg_color_list, bg_color_list) 
    230      
    231     def get_html_of_marked_pathway_by_objects(self, pathway_id, object_id_list): 
    232         return self.service.get_html_of_marked_pathway_by_objects(pathway_id, object_id_list) 
    233      
    234     def get_html_of_colored_pathway_by_objects(self, pathway_id, object_id_list, fg_color_list, bg_color_list): 
    235         return self.service.get_html_of_colored_pathway_by_objects(pathway_id, object_id_list, fg_color_list, bg_color_list) 
    236      
    237     def get_html_of_colored_pathway_by_elements(self, pathway_id, element_id_list, fg_color_list, bg_color_list): 
    238         return self.service.get_html_of_colored_pathway_by_elements(pathway_id, element_id_list, fg_color_list, bg_color_list) 
    239      
     212        raise NotImplementedError 
     213 
     214    def color_pathway_by_objects(self, pathway_id, object_id_list, 
     215                                 fg_color_list, bg_color_list): 
     216        raise NotImplementedError 
     217 
     218    def color_pathway_by_elements(self, pathway_id, element_id_list, 
     219                                  fg_color_list, bg_color_list): 
     220        raise NotImplementedError 
     221 
     222    def get_html_of_marked_pathway_by_objects(self, pathway_id, 
     223                                              object_id_list): 
     224        raise NotImplementedError 
     225 
     226    def get_html_of_colored_pathway_by_objects(self, pathway_id, 
     227                                               object_id_list, fg_color_list, 
     228                                               bg_color_list): 
     229        raise NotImplementedError 
     230 
     231    def get_html_of_colored_pathway_by_elements(self, pathway_id, 
     232                                                element_id_list, fg_color_list, 
     233                                                bg_color_list): 
     234        raise NotImplementedError 
     235 
    240236    def get_references_by_pathway(self, pathway_id): 
    241237        return self.service.get_references_by_pathway(pathway_id) 
    242      
     238 
    243239    def get_element_relations_by_pathway(self, pathway_id): 
    244240        return self.service.get_element_relations_by_pathway(pathway_id) 
    245      
    246      
    247      
     241 
    248242    def get_genes_by_organism(self, organism, offset=None, limit=None): 
    249         if offset is None and limit is None: 
    250             offset = 0 
    251             limit = self.get_number_of_genes_by_organism(organism) 
    252              
    253         return self.service.get_genes_by_organism(organism, offset, limit) 
    254      
     243        if offset is not None: 
     244            raise NotImplementedError("offset is no longer supported") 
     245        if limit is not None: 
     246            raise NotImplementedError("limit is no longer supported.") 
     247 
     248        res = self.service.list(organism).get().splitlines() 
     249        return [r.split(None, 1)[0] for r in res] 
     250 
    255251    def get_number_of_genes_by_organism(self, organism): 
    256         return self.service.get_number_of_genes_by_organism(organism) 
    257      
     252        raise NotImplementedError 
     253 
    258254    #################### 
    259255    # Objects by pathway 
    260256    #################### 
    261      
     257 
    262258    def get_elements_by_pathway(self, pathway_id): 
    263         return self.service.get_elements_by_pathway(pathway_id) 
    264      
     259        raise NotImplementedError 
     260 
    265261    def get_genes_by_pathway(self, pathway_id): 
    266         return self.service.get_genes_by_pathway(pathway_id) 
    267      
     262        return _link_targets(self.link("genes", ids=[pathway_id])) 
     263 
    268264    def get_enzymes_by_pathway(self, pathway_id): 
    269         return self.service.get_enzymes_by_pathway(pathway_id) 
    270      
     265        return _link_targets(self.link("ec", ids=[pathway_id])) 
     266 
    271267    def get_compounds_by_pathway(self, pathway_id): 
    272         return self.service.get_compounds_by_pathway(pathway_id) 
    273      
     268        return _link_targets(self.link("compound", ids=[pathway_id])) 
     269 
    274270    def get_drugs_by_pathway(self, pathway_id): 
    275         return self.service.get_drugs_by_pathway(pathway_id) 
    276      
     271        return _link_targets(self.link("drug", ids=[pathway_id])) 
     272 
    277273    def get_glycans_by_pathway(self, pathway_id): 
    278         return self.service.get_glycans_by_pathway(pathway_id) 
    279      
     274        return _link_targets(self.link("gl", ids=[pathway_id])) 
     275 
    280276    def get_reactions_by_pathway(self, pathway_id): 
    281         return self.get_reactions_by_pathway(pathway_id) 
    282      
     277        return _link_targets(self.link("rn", ids=[pathway_id])) 
     278 
    283279    def get_kos_by_pathway(self, pathway_id): 
    284         return self.service.get_kos_by_pathway(pathway_id) 
    285      
     280        return _link_targets(self.link("ko", ids=[pathway_id])) 
     281 
    286282    ##################### 
    287283    # Pathways by objects 
    288284    ##################### 
    289      
     285 
     286    # These functions returned results intersections. 
    290287    def get_pathways_by_genes(self, gene_list): 
    291         return map(str, self.service.get_pathways_by_genes(gene_list)) 
    292      
     288        raise NotImplementedError 
     289 
    293290    def get_pathways_by_enzymes(self, enzyme_list): 
    294         return map(str, self.service.get_pathways_by_enzymes(enzyme_list)) 
    295      
     291        raise NotImplementedError 
     292 
    296293    def get_pathways_by_compounds(self, compound_list): 
    297         return map(str, self.service.get_pathways_by_compounds(compound_list)) 
    298      
     294        raise NotImplementedError 
     295 
    299296    def get_pathways_by_drugs(self, drug_list): 
    300         return map(str, self.service.get_pathways_by_drugs(drug_list)) 
    301      
     297        raise NotImplementedError 
     298 
    302299    def get_pathways_by_glycans(self, glycan_list): 
    303         return map(str, self.service.get_pathways_by_glycans(glycan_list)) 
    304      
     300        raise NotImplementedError 
     301 
    305302    def get_pathways_by_reactions(self, reaction_list): 
    306         return map(str, self.service.get_pathways_by_reactions(reaction_list)) 
    307      
     303        raise NotImplementedError 
     304 
    308305    def get_pathways_by_kos(self, ko_list): 
    309         return map(str, self.service.get_pathways_by_kos(ko_list)) 
    310      
     306        raise NotImplementedError 
     307 
    311308    ########################## 
    312309    # Relations among pathways 
    313310    ########################## 
    314      
     311 
    315312    def get_linked_pathways(self, pathway_id): 
    316313        if not pathway_id.startswith("path:"): 
    317314            pathway_id = "path:" + pathway_id 
    318         return map(str, self.service.get_linked_pathways(pathway_id)) 
    319      
    320      
     315        return _link_targets(self.link("pathway", ids=[pathway_id])) 
     316 
     317 
    321318""" 
    322319KEGG api with caching 
     
    355352    def set_default_release(self, release): 
    356353        self.default_release = release 
    357          
    358      
    359     ################## 
    360     # Meta information 
    361     ################## 
    362      
    363     @lru_cache() # not persistently cached 
    364     def list_databases(self): 
    365         return KeggApi.list_databases(self) 
    366      
     354 
    367355    @cached_method 
    368356    def list_organisms(self): 
     
    372360    def list_pathways(self, organism): 
    373361        return KeggApi.list_pathways(self, organism) 
    374      
    375     ####### 
    376     # DBGET 
    377     ####### 
    378      
    379     @lru_cache() # not persistently cached 
    380     def binfo(self, db): 
    381         return KeggApi.binfo(self, db) 
    382      
    383     @cached_method 
    384     def bfind(self, db, keywords): 
    385         return KeggApi.bfind(self, db, keywords) 
    386      
    387     @cached_method 
    388     def bget(self, ids): 
    389         rval = KeggApi.bget(self, ids) 
    390         return rval 
    391      
    392     @cached_method 
    393     def bget(self, ids): 
     362 
     363    @cached_method 
     364    def list(self, db): 
     365        return KeggApi.list(self, db) 
     366 
     367    @lru_cache()  # not persistently cached 
     368    def info(self, db): 
     369        return KeggApi.info(self, db) 
     370 
     371    @cached_method 
     372    def find(self, db, keywords): 
     373        return KeggApi.find(self, db, keywords) 
     374 
     375    @cached_method 
     376    def get(self, ids): 
    394377        if not isinstance(ids, basestring): 
    395             return self._batch_bget(ids) 
     378            return self._batch_get(ids) 
    396379        else: 
    397             return KeggApi.bget(self, ids) 
    398          
    399     def _batch_bget(self, ids): 
    400         if len(ids) > 100: 
    401             raise ValueError("Can batch at most 100 ids at a time.") 
    402          
    403         bget = self.bget 
     380            return KeggApi.get(self, ids) 
     381 
     382    def _batch_get(self, ids): 
     383        if len(ids) > 10: 
     384            raise ValueError("Can batch at most 10 ids at a time.") 
     385 
     386        get = self.get 
    404387        uncached = [] 
    405         with closing(bget.cache_store()) as store: 
     388        unmatched = set() 
     389 
     390        with closing(get.cache_store()) as store: 
    406391            # Which ids are already cached 
    407392            # TODO: Invalidate entries by release string. 
    408393            for id in ids: 
    409                 key = bget.key_from_args((id,)) 
     394                key = get.key_from_args((id,)) 
    410395                if key not in store: 
    411396                    uncached.append(id) 
    412                  
     397 
    413398        if uncached: 
    414399            # in case there are duplicate ids 
    415400            uncached = sorted(set(uncached)) 
    416             rval = KeggApi.bget(self, uncached) 
     401            rval = KeggApi.get(self, uncached) 
     402 
    417403            if rval is not None: 
    418                 entrys = rval.split("///\n") 
     404                entries = rval.split("///\n") 
    419405            else: 
    420                 entrys = [] 
    421                  
    422             if entrys and not entrys[-1].strip(): 
    423                 # Delete the last newline if present 
    424                 del entrys[-1] 
    425              
    426             if len(entrys) == len(uncached): 
    427                 with closing(bget.cache_store()) as store: 
    428                     for id, entry in zip(uncached, entrys): 
    429                         key = bget.key_from_args((id,)) 
    430                         if entry is not None: 
    431                             entry = entry + "///\n" 
    432                         store[key] = cache_entry(entry, mtime=datetime.now()) 
    433                          
    434             else: 
    435                 # Try to bisect the uncached list 
    436                 if len(uncached) > 1 and len(uncached) - len(entrys) < 4: 
    437                     split = len(uncached) / 2 
    438                     self._batch_bget(uncached[:split]) 
    439                     self._batch_bget(uncached[split:]) 
    440                 else: 
    441                     import warnings 
    442                     warnings.warn("Batch contains invalid ids", UserWarning) 
    443          
     406                entries = [] 
     407 
     408            if entries and not entries[-1].strip(): 
     409                # Delete the last single newline entry if present 
     410                del entries[-1] 
     411 
     412            if len(entries) != len(uncached): 
     413                new_uncached, entries = match_by_ids(uncached, entries) 
     414                unmatched = set(uncached) - set(new_uncached) 
     415                uncached = new_uncached 
     416                warnings.warn("Unable to match entries for keys: %s." % 
     417                              ", ".join(map(repr, unmatched))) 
     418 
     419            with closing(get.cache_store()) as store: 
     420                for id, entry in zip(uncached, entries): 
     421                    key = get.key_from_args((id,)) 
     422                    if entry is not None: 
     423                        entry = entry + "///\n" 
     424                    store[key] = cache_entry(entry, mtime=datetime.now()) 
     425 
    444426        # Finally join all the results, but drop all None objects 
    445         entries = filter(lambda e: e is not None, map(bget, ids)) 
    446          
     427        entries = filter(lambda e: e is not None, map(get, ids)) 
     428 
    447429        rval = "".join(entries) 
    448430        return rval 
    449      
    450     @cached_method 
    451     def btit(self, ids): 
    452         return KeggApi.btit(self, ids) 
    453      
    454     @cached_method 
    455     def bconv(self, ids): 
    456         return KeggApi.bconv(self, ids) 
    457      
     431 
     432    @cached_method 
     433    def conv(self, ids): 
     434        return KeggApi.conv(self, ids) 
     435 
    458436    ######## 
    459437    # LinkDB 
    460438    ######## 
    461      
    462     @cached_method 
    463     def get_linkdb_by_entry(self, entry_id, db, offset, limit): 
    464        return KeggApi.get_linkdb_by_entry(self, entry_id, db, offset, limit) 
    465          
    466     @cached_method 
    467     def get_linkdb_between_databases(self, from_db, to_db, offset, limit): 
    468         return KeggApi.get_linkdb_between_databases(self, from_db, to_db, offset, limit) 
    469              
     439 
    470440    @cached_method 
    471441    def get_genes_by_enzyme(self, enzyme_id, org): 
    472442        return KeggApi.get_genes_by_enzyme(self, enzyme_id, org) 
    473      
     443 
    474444    @cached_method 
    475445    def get_enzymes_by_gene(self, genes_id): 
    476446        return KeggApi.get_enzymes_by_gene(self, genes_id) 
    477      
     447 
    478448    @cached_method 
    479449    def get_enzymes_by_compound(self, compound_id): 
    480450        return KeggApi.get_enzymes_by_compound(self, compound_id) 
    481      
     451 
    482452    @cached_method 
    483453    def get_enzymes_by_glycan(self, glycan_id): 
    484454        return KeggApi.get_enzymes_by_glycan(self, glycan_id) 
    485      
     455 
    486456    @cached_method 
    487457    def get_enzymes_by_reaction(self, reaction_id): 
    488458        return KeggApi.get_enzymes_by_reaction(self, reaction_id) 
    489      
     459 
    490460    @cached_method 
    491461    def get_compounds_by_enzyme(self, enzyme_id): 
    492462        return KeggApi.get_compounds_by_enzyme(self, enzyme_id) 
    493      
     463 
    494464    @cached_method 
    495465    def get_compounds_by_reaction(self, reaction_id): 
    496466        return KeggApi.get_compounds_by_reaction(self, reaction_id) 
    497      
     467 
    498468    @cached_method 
    499469    def get_glycans_by_enzyme(self, enzyme_id): 
    500470        return KeggApi.get_glycans_by_enzyme(self, enzyme_id) 
    501      
     471 
    502472    @cached_method 
    503473    def get_glycans_by_reaction(self, reaction_id): 
    504474        return KeggApi.get_glycans_by_reaction(self, reaction_id) 
    505      
     475 
    506476    @cached_method 
    507477    def get_reactions_by_enzyme(self, enzyme_id): 
    508478        return KeggApi.get_reactions_by_enzyme(self, enzyme_id) 
    509      
     479 
    510480    @cached_method 
    511481    def get_reactions_by_compound(self, compound_id): 
    512482        return KeggApi.get_reactions_by_compound(self, compound_id) 
    513      
     483 
    514484    @cached_method 
    515485    def get_reactions_by_glycan(self, glycan_id): 
    516486        return KeggApi.get_reactions_by_glycan(self, glycan_id) 
    517      
     487 
    518488    ###### 
    519489    # SSDB 
     
    571541    # Pathway 
    572542    ######### 
    573      
    574     # TODO 
    575      
    576      
    577      
     543 
    578544    @cached_method 
    579545    def get_genes_by_organism(self, organism, offset=None, limit=None): 
     
    643609    def get_kos_by_pathway(self, pathway_id): 
    644610        return KeggApi.get_kos_by_pathway(self, pathway_id) 
    645      
     611 
     612 
     613def match_by_ids(ids, entries): 
     614    """ 
     615 
     616    """ 
     617 
     618    unmatched_ids = set(ids) 
     619    unmatched_entries = set(entries) 
     620 
     621    matched_ids = [] 
     622    matched_entries = [] 
     623 
     624    def match_add(search_id, entry): 
     625        """ 
     626        Move search_id and entry to the matched lists. 
     627        """ 
     628        matched_ids.append(search_id) 
     629        matched_entries.append(entry) 
     630 
     631        # Remove from the unmatched set 
     632        unmatched_ids.remove(search_id) 
     633        unmatched_entries.remove(entry) 
     634 
     635    def entry_split(entry_text): 
     636        line, _ = entry_text.split("\n", 1) 
     637        return line.split(None, 2) 
     638 
     639    entries_by_id = {} 
     640 
     641    for entry in entries: 
     642        _, eid, _ = entry_split(entry) 
     643        entries_by_id[eid] = entry 
     644 
     645    # First match full search ids 
     646    for search_id in list(unmatched_ids): 
     647        if search_id in entries_by_id: 
     648            entry = entries_by_id.pop(search_id) 
     649            match_add(search_id, entry) 
     650 
     651    # Second pass, split the search ids by ':' to db and identifier part, 
     652    # match by identifier 
     653    for search_id in list(unmatched_ids): 
     654        if ":" in search_id: 
     655            db_id, rest = search_id.split(":", 1) 
     656            if rest in entries_by_id: 
     657                entry = entries_by_id.pop(rest) 
     658                match_add(search_id, entry) 
     659 
     660    return matched_ids, matched_entries 
  • _bioinformatics/obiKEGG/databases.py

    r1716 r1733  
    1010from . import api 
    1111 
     12 
    1213def iter_take(source_iter, n): 
    1314    source_iter = iter(source_iter) 
    1415    return [item for _, item in zip(range(n), source_iter)] 
     16 
    1517 
    1618def batch_iter(source_iter, n): 
     
    2224        else: 
    2325            break 
    24          
     26 
     27 
    2528def chain_iter(chains_iter): 
    2629    for iter in chains_iter: 
     
    2831            yield element 
    2932 
     33 
     34# TODO: DBDataBase should be able to be constructed from a flat text 
     35# entry file. The precache etc. should be moved in caching api, that creates 
     36# simple file system hierarchy where the flat database is saved (with db 
     37# release string), e.g. 
     38# genes/hsa.dbget 
     39# genes/hsa.release 
     40# genes/sce.dbget 
     41# path.dbget 
     42# module.dbget 
     43# ligand/compound.dbget 
     44 
     45 
    3046class DBDataBase(object): 
    31     """ A wrapper for DBGET database. 
     47    """ 
     48    A wrapper for DBGET database. 
     49 
    3250    """ 
    3351    # ENTRY_TYPE constructor (type) 
    3452    ENTRY_TYPE = entry.DBEntry 
    35      
    36     # Needs to be set in a subclass or object instance  
     53 
     54    # A database name/abbreviation (e.g. path). Needs to be set in a 
     55    # subclass or object instance's constructor 
    3756    DB = None 
    38      
     57 
    3958    def __init__(self, **kwargs): 
    4059        if not self.DB: 
    41             raise TypeError("Cannot make an instance of abstract base class %r." \ 
    42                             % type(self).__name__) 
    43              
     60            raise TypeError("Cannot make an instance of abstract base " 
     61                            "class %r." % type(self).__name__) 
     62 
    4463        self.api = api.CachedKeggApi() 
    45         self.info = self.api.binfo(self.DB) 
     64        self.info = self.api.info(self.DB) 
    4665        release = self.info.release 
    4766        self.api.set_default_release(release) 
    4867        self._keys = [] 
    49          
     68 
    5069    def keys(self): 
     70        """ 
     71        Return a list of database keys. These are unique kegg identifiers 
     72        that can be used to query the database. 
     73 
     74        """ 
    5175        return list(self._keys) 
    52      
     76 
    5377    def iterkeys(self): 
     78        """ 
     79        Return an iterator over the `keys` 
     80        """ 
    5481        return iter(self._keys) 
    55      
     82 
    5683    def items(self): 
     84        """ 
     85        Return a list of all (key, `ENTRY_TYPE` instance) tuples. 
     86        """ 
    5787        return list(zip(self.keys(), self.batch_get(self.keys()))) 
    58      
     88 
    5989    def iteritems(self): 
     90        """ 
     91        Return an iterator over the `items`. 
     92        """ 
    6093        batch_size = 100 
    6194        iterkeys = self.iterkeys() 
    6295        return chain_iter(zip(batch, self.batch_get(batch)) 
    6396                          for batch in batch_iter(iterkeys, batch_size)) 
    64          
    65 #        return ((key, self.__getitem__(key)) for key in self.iterkeys()) 
    66      
     97 
    6798    def values(self): 
     99        """ 
     100        Return a list of all `ENTRY_TYPE` instances. 
     101        """ 
    68102        return self.batch_get(self.keys()) 
    69      
     103 
    70104    def itervalues(self): 
     105        """ 
     106        Return an iterator over all `ENTRY_TYPE` instances. 
     107        """ 
    71108        batch_size = 100 
    72109        iterkeys = self.iterkeys() 
    73110        return chain_iter(self.batch_get(batch) 
    74111                          for batch in batch_iter(iterkeys, batch_size)) 
    75          
    76 #        return (self.__getitem__(key) for key in self.iterkeys()) 
    77      
     112 
    78113    def get(self, key, default=None): 
     114        """ 
     115        Return an `ENTRY_TYPE` instance for the `key`. Raises `KeyError` if 
     116        not found. 
     117 
     118        """ 
    79119        try: 
    80120            return self.__getitem__(key) 
    81121        except KeyError: 
    82122            return default 
    83          
     123 
    84124    def has_key(self, key): 
    85125        return self.__contains__(key) 
    86      
     126 
    87127    def __getitem__(self, key): 
    88128        e = self.get_entry(key) 
     
    91131        else: 
    92132            return e 
    93      
     133 
    94134    def __contains__(self, key): 
    95135        return key in set(self.keys()) 
    96      
     136 
    97137    def __len__(self): 
    98138        return len(self.keys()) 
    99      
     139 
    100140    def __iter__(self): 
    101141        return iter(self.keys()) 
    102      
     142 
    103143    def get_text(self, key): 
     144        """ 
     145        Return the database entry for `key` as plain text. 
     146        """ 
    104147        key = self._add_db(key) 
    105         return self.api.bget([key]) 
    106      
     148        return self.api.get([key]) 
     149 
    107150    def get_entry(self, key): 
     151        """ 
     152        Return the database entry for `key` as an instance of `ENTRY_TYPE`. 
     153        """ 
    108154        text = self.get_text(key) 
    109155        if not text or text == "None": 
     
    111157        else: 
    112158            return self.ENTRY_TYPE(text) 
    113          
     159 
    114160    def find(self, name): 
    115         """ Find ``name`` using BFIND.  
    116         """ 
    117         res = self.api.bfind(self.DB, name).splitlines() 
    118         return [r.split(" ", 1)[0] for r in res]     
    119          
    120     def pre_cache(self, keys=None, batch_size=100, progress_callback=None): 
    121         """ Retrive all the entries and cache them locally. 
     161        """ 
     162        Find ``name`` using kegg ``find`` api. 
     163        """ 
     164        res = self.api.find(self.DB, name).splitlines() 
     165        return [r.split(" ", 1)[0] for r in res] 
     166 
     167    def pre_cache(self, keys=None, batch_size=10, progress_callback=None): 
     168        """ 
     169        Retrieve all the entries and cache them locally. 
    122170        """ 
    123171        # TODO do this in multiple threads 
    124      
     172 
    125173        if not isinstance(self.api, api.CachedKeggApi): 
    126             raise TypeError("Not an an instance of api.CachedKeggApi") 
    127          
    128         if batch_size > 100 or batch_size < 1: 
     174            raise TypeError("Not an instance of api.CachedKeggApi") 
     175 
     176        if batch_size > 10 or batch_size < 1: 
    129177            raise ValueError("Invalid batch_size") 
    130          
     178 
    131179        if keys is None: 
    132180            keys = self.keys() 
    133              
     181 
    134182        keys = list(keys) 
    135183        start = 0 
     
    137185            batch = keys[start: start + batch_size] 
    138186            batch = map(self._add_db, batch) 
    139              
    140             self.api.bget(batch) 
    141              
     187 
     188            self.api.get(batch) 
     189 
    142190            if progress_callback: 
    143191                progress_callback(100.0 * start / len(keys)) 
    144                  
     192 
    145193            start += batch_size 
    146              
     194 
    147195    def batch_get(self, keys): 
    148         """ Batch retrieve all entries for keys. This can be 
    149         significantly faster then getting each entry separately 
    150         especially if entries are not yet cached. 
    151          
     196        """ 
     197        Batch retrieve all entries for keys. This can be significantly 
     198        faster then getting each entry separately especially if entries 
     199        are not yet cached. 
     200 
    152201        """ 
    153202        entries = [] 
     
    158207            batch = keys[start: start + batch_size] 
    159208            batch = map(self._add_db, batch) 
    160             batch_entries = self.api.bget(batch) 
     209            batch_entries = self.api.get(batch) 
    161210            if batch_entries is not None: 
    162211                batch_entries = batch_entries.split("///\n") 
    163                 # Remove possible empty last line   
     212                # Remove possible empty last line 
    164213                batch_entries = [e for e in batch_entries if e.strip()] 
    165214                entries.extend(map(self.ENTRY_TYPE, batch_entries)) 
    166215            start += batch_size 
    167              
     216 
    168217        return entries 
    169              
     218 
    170219    def _add_db(self, key): 
    171         """ Prefix the key with '%(DB)s:' string if not already 
    172         prefixed.  
     220        """ 
     221        Prefix the key with '%(DB)s:' string if not already prefixed. 
    173222        """ 
    174223        if not key.startswith(self.DB + ":"): 
     
    176225        else: 
    177226            return key 
    178          
    179     @property 
    180     def entries(self): 
    181         return self.values() 
    182      
     227 
     228 
    183229@entry.entry_decorate 
    184230class GenomeEntry(entry.DBEntry): 
    185     FIELDS = [("ENTRY", fields.DBEntryField), 
    186               ("NAME", fields.DBNameField), 
    187               ("DEFINITION", fields.DBDefinitionField), 
    188               ("ANNOTATION", fields.DBSimpleField), 
    189               ("TAXONOMY", fields.DBTaxonomyField), 
    190               ("DATA_SOURCE", fields.DBSimpleField), 
    191               ("ORIGINAL_DB", fields.DBSimpleField), 
    192               ("KEYWORDS", fields.DBSimpleField), 
    193               ("DISEASE", fields.DBSimpleField), 
    194               ("COMMENT", fields.DBSimpleField), 
    195               ("CHROMOSOME", fields.DBFieldWithSubsections), 
    196               ("STATISTICS", fields.DBSimpleField), 
    197               ("REFERENCE", fields.DBReference)] 
    198      
     231    """ 
     232    Entry for a KEGG Genome database. 
     233    """ 
     234    FIELDS = [ 
     235        ("ENTRY", fields.DBEntryField), 
     236        ("NAME", fields.DBNameField), 
     237        ("DEFINITION", fields.DBDefinitionField), 
     238        ("ANNOTATION", fields.DBSimpleField), 
     239        ("TAXONOMY", fields.DBTaxonomyField), 
     240        ("DATA_SOURCE", fields.DBSimpleField), 
     241        ("ORIGINAL_DB", fields.DBSimpleField), 
     242        ("KEYWORDS", fields.DBSimpleField), 
     243        ("DISEASE", fields.DBSimpleField), 
     244        ("COMMENT", fields.DBSimpleField), 
     245        ("CHROMOSOME", fields.DBFieldWithSubsections), 
     246        ("PLASMID", fields.DBSimpleField), 
     247        ("STATISTICS", fields.DBSimpleField), 
     248        ("REFERENCE", fields.DBReference) 
     249    ] 
     250 
    199251    MULTIPLE_FIELDS = ["REFERENCE"] 
    200      
     252 
    201253    def __init__(self, text): 
    202254        entry.DBEntry.__init__(self, text) 
    203          
     255 
    204256    @property 
    205     def entry_key(self): 
    206         """ Primary entry key used for querying. 
    207          
    208         .. note:: Unlike most of the other entry types this is the 
    209             first listed 'NAME'. 
    210              
    211         """ 
    212          
     257    def organism_code(self): 
     258        """ 
     259        A three or four letter KEGG organism code (e.g. 'hsa', 'sce', ...) 
     260        """ 
    213261        return self.name.split(",", 1)[0] 
    214262 
    215263    @property 
    216264    def taxid(self): 
     265        """ 
     266        Organism NCBI taxonomy id. 
     267        """ 
    217268        return self.TAXONOMY.taxid 
    218              
    219     def org_code(self): 
    220         if self.name is not None: 
    221             return self.name.split(",")[0] 
    222         else: 
    223             return self.entry.split(" ")[0] 
    224          
     269 
     270#    def org_code(self): 
     271#        if self.name is not None: 
     272#            return self.name.split(",")[0] 
     273#        else: 
     274#            return self.entry.split(" ")[0] 
     275 
    225276 
    226277class Genome(DBDataBase): 
     278    """ 
     279    An interface to the A KEGG GENOME database. 
     280    """ 
    227281    DB = "genome" 
    228282    ENTRY_TYPE = GenomeEntry 
    229      
     283 
    230284    # For obiTaxonomy.common_taxids mapping 
    231     TAXID_MAP = {"562": "511145",   # Escherichia coli K-12 MG1655 
    232                  "2104": "272634",  # Mycoplasma pneumoniae M129  
    233                  "4530": "39947",   # Oryza sativa ssp. japonica cultivar Nipponbare (Japanese rice) 
    234                  "4932" : "559292", # Saccharomyces cerevisiae S288C 
    235                  "4896": "284812",  # Schizosaccharomyces pombe 972h- 
    236                  } 
    237      
     285    TAXID_MAP = { 
     286        "562": "511145",   # Escherichia coli K-12 MG1655 
     287        "2104": "272634",  # Mycoplasma pneumoniae M129 
     288        "4530": "39947",   # Oryza sativa ssp. japonica cultivar Nipponbare (Japanese rice) 
     289        "4932": "559292",  # Saccharomyces cerevisiae S288C 
     290        "4896": "284812",  # Schizosaccharomyces pombe 972h- 
     291    } 
     292 
    238293    def __init__(self): 
    239294        DBDataBase.__init__(self) 
    240         self._keys = [org.entry_id for org in self.api.list_organisms()] 
    241      
     295        self._org_list = self.api.list_organisms() 
     296        self._keys = [org.entry_id for org in self._org_list] 
     297 
    242298    def _key_to_gn_entry_id(self, key): 
    243299        res = self.find(key) 
     
    248304        else: 
    249305            return res[0] 
    250      
     306 
    251307    @classmethod 
    252308    def common_organisms(cls): 
     
    254310                'dme', 'eco', 'hsa', 'mmu', 'mpn', 'osa', 
    255311                'pfa', 'rno', 'sce', 'spo', 'zma', 'xla'] 
    256          
     312 
    257313    @classmethod 
    258314    def essential_organisms(cls): 
    259315        return ['ddi', 'dme', 'hsa', 'mmu', 'sce'] 
    260      
     316 
     317    def org_code_to_entry_key(self, code): 
     318        """ 
     319        Map an organism code ('hsa', 'sce', ...) to the corresponding kegg 
     320        identifier (T + 5 digit number). 
     321 
     322        """ 
     323        for org in self._org_list: 
     324            if org.org_code == code: 
     325                return org.entry_id 
     326        else: 
     327            raise ValueError("Unknown organism code '%s'" % code) 
     328 
    261329    def search(self, string, relevance=False): 
    262         """ Search the genome database for string using ``bfind``. 
     330        """ 
     331        Search the genome database for string using ``bfind``. 
    263332        """ 
    264333        if relevance: 
    265334            raise NotImplementedError("relevance is no longer supported") 
     335 
    266336        if string in self.TAXID_MAP: 
    267337            string = self.TAXID_MAP[string] 
    268              
    269         res = self.api.bfind(self.DB, string) 
     338 
     339        res = self.api.find(self.DB, string) 
    270340        if not res: 
    271341            return [] 
    272          
     342 
    273343        res = res.splitlines() 
    274344        res = [r.split(",", 1)[0] for r in res] 
    275         res = [r.split(" ", 1)[1] for r in res] 
     345        res = [r.split(None, 1)[1] for r in res] 
    276346        return res 
    277      
    278      
     347 
     348 
    279349@entry.entry_decorate 
    280350class GeneEntry(entry.DBEntry): 
    281     FIELDS = [("ENTRY", fields.DBEntryField), 
    282               ("NAME", fields.DBNameField), 
    283               ("DEFINITION", fields.DBDefinitionField), 
    284               ("ORGANISM", fields.DBSimpleField), 
    285               ("ORTHOLOGY", fields.DBSimpleField), 
    286               ("DRUG_TARGET", fields.DBSimpleField), 
    287               ("PATHWAY", fields.DBPathway), 
    288               ("MODULE", fields.DBSimpleField), 
    289               ("DISEASE", fields.DBSimpleField), 
    290               ("CLASS", fields.DBSimpleField), 
    291               ("POSITION", fields.DBSimpleField), 
    292               ("MOTIF", fields.DBSimpleField), 
    293               ("DBLINKS", fields.DBDBLinks), 
    294               ("STRUCTURE", fields.DBSimpleField), 
    295               ("AASEQ", fields.DBAASeq), 
    296               ("NTSEQ", fields.DBNTSeq)] 
    297      
     351    FIELDS = [ 
     352        ("ENTRY", fields.DBEntryField), 
     353        ("NAME", fields.DBNameField), 
     354        ("DEFINITION", fields.DBDefinitionField), 
     355        ("ORTHOLOGY", fields.DBSimpleField), 
     356        ("ORGANISM", fields.DBSimpleField), 
     357        ("PATHWAY", fields.DBPathway), 
     358        ("MODULE", fields.DBSimpleField), 
     359        ("DISEASE", fields.DBSimpleField), 
     360        ("DRUG_TARGET", fields.DBSimpleField), 
     361        ("CLASS", fields.DBSimpleField), 
     362        ("MOTIF", fields.DBSimpleField), 
     363        ("DBLINKS", fields.DBDBLinks), 
     364        ("STRUCTURE", fields.DBSimpleField), 
     365        ("POSITION", fields.DBSimpleField), 
     366        ("AASEQ", fields.DBAASeq), 
     367        ("NTSEQ", fields.DBNTSeq) 
     368    ] 
     369 
    298370    def aliases(self): 
    299         return [self.entry_key] + (self.name.split(",") if self.name else []) + [link[1][0] for link in self.dblinks.items() if self.dblinks] 
     371        return [self.entry_key] + \ 
     372               (self.name.split(",") if self.name else []) + \ 
     373               ([link[1][0] for link in self.dblinks.items()] 
     374                if self.dblinks else []) 
    300375 
    301376    @property 
    302377    def alt_names(self): 
    303         """ For backwards compatibility. 
     378        """ 
     379        For backwards compatibility. 
    304380        """ 
    305381        return self.aliases() 
    306    
     382 
     383 
    307384class Genes(DBDataBase): 
    308     DB = None # Needs to be set in __init__  
     385    DB = None  # Needs to be set in __init__ 
    309386    ENTRY_TYPE = GeneEntry 
    310      
     387 
    311388    def __init__(self, org_code): 
     389        # TODO: Map to org code from kegg id (T + 5 digits) 
    312390        self.DB = org_code 
    313391        self.org_code = org_code 
    314392        DBDataBase.__init__(self) 
    315393        self._keys = self.api.get_genes_by_organism(org_code) 
    316          
     394 
    317395    def gene_aliases(self): 
    318396        aliases = {} 
    319397        for entry in self.itervalues(): 
    320             aliases.update(dict.fromkeys(entry.aliases(), self.org_code + ":" + entry.entry_key())) 
     398            aliases.update(dict.fromkeys(entry.aliases(), 
     399                                         self.org_code + ":" + entry.entry_key)) 
    321400        return aliases 
    322      
     401 
    323402 
    324403@entry.entry_decorate 
    325404class CompoundEntry(entry.DBEntry): 
    326     FIELDS = [("ENTRY", fields.DBEntryField), 
    327               ("NAME", fields.DBNameField), 
    328               ("FORMULA", fields.DBSimpleField), 
    329               ("MASS", fields.DBSimpleField), 
    330               ("REMARK", fields.DBSimpleField), 
    331               ("REACTION", fields.DBSimpleField), 
    332               ("PATHWAY", fields.DBPathway), 
    333               ("ENZYME", fields.DBSimpleField), 
    334               ("DBLINKS", fields.DBDBLinks), 
    335               ("ATOM", fields.DBSimpleField), 
    336               ("BOND", fields.DBSimpleField) 
    337               ] 
    338      
    339      
    340 class Compounds(DBDataBase): 
     405    FIELDS = [ 
     406        ("ENTRY", fields.DBEntryField), 
     407        ("NAME", fields.DBNameField), 
     408        ("FORMULA", fields.DBSimpleField), 
     409        ("EXACT_MASS", fields.DBSimpleField), 
     410        ("MOL_WEIGHT", fields.DBSimpleField), 
     411        ("REMARK", fields.DBSimpleField), 
     412        ("COMMENT", fields.DBSimpleField), 
     413        ("REACTION", fields.DBSimpleField), 
     414        ("PATHWAY", fields.DBPathway), 
     415        ("ENZYME", fields.DBSimpleField), 
     416        ("BRITE", fields.DBSimpleField), 
     417        ("REFERENCE", fields.DBSimpleField), 
     418        ("DBLINKS", fields.DBDBLinks), 
     419        ("ATOM", fields.DBSimpleField), 
     420        ("BOND", fields.DBSimpleField) 
     421    ] 
     422 
     423 
     424class Compound(DBDataBase): 
    341425    DB = "cpd" 
    342426    ENTRY_TYPE = CompoundEntry 
    343      
     427 
    344428    def __init__(self): 
    345429        DBDataBase.__init__(self) 
    346         self._keys = [] # All keys are not available 
    347  
    348  
    349 @entry.entry_decorate     
     430        self._keys = [d.entry_id for d in self.api.list("cpd")] 
     431 
     432 
     433@entry.entry_decorate 
    350434class ReactionEntry(entry.DBEntry): 
    351     FIELDS = [("ENTRY", fields.DBEntryField), 
    352               ("NAME", fields.DBNameField), 
    353               ("DEFINITION", fields.DBDefinitionField), 
    354               ("EQUATION", fields.DBSimpleField), 
    355               ("ENZYME", fields.DBSimpleField) 
    356               ] 
    357      
    358 class Reactions(DBDataBase): 
     435    FIELDS = [ 
     436        ("ENTRY", fields.DBEntryField), 
     437        ("NAME", fields.DBNameField), 
     438        ("DEFINITION", fields.DBDefinitionField), 
     439        ("EQUATION", fields.DBSimpleField), 
     440        ("ENZYME", fields.DBSimpleField) 
     441    ] 
     442 
     443 
     444class Reaction(DBDataBase): 
    359445    DB = "rn" 
    360446    ENTRY_TYPE = ReactionEntry 
    361      
     447 
    362448    def __init__(self): 
    363449        DBDataBase.__init__(self) 
    364         self._keys = [] # All keys are not available 
    365           
     450        self._keys = [d.entry_id for d in self.api.list("rn")] 
     451 
     452 
    366453class Brite(DBDataBase): 
    367454    DB = "br" 
    368      
     455 
     456 
    369457class Disease(DBDataBase): 
    370458    DB = "ds" 
    371          
     459 
     460 
    372461class Drug(DBDataBase): 
    373462    DB = "dr" 
    374      
     463 
     464 
    375465@entry.entry_decorate 
    376466class EnzymeEntry(entry.DBEntry): 
    377     FIELDS = [("ENTRY", fields.DBEntryField), 
    378               ("NAME", fields.DBNameField), 
    379               ("CLASS", fields.DBSimpleField), 
    380               ("SYSNAME", fields.DBSimpleField), 
    381               ("REACTION", fields.DBSimpleField), 
    382               ("ALL_REAC", fields.DBSimpleField), 
    383               ("SUBSTRATE", fields.DBSimpleField), 
    384               ("PRODUCT", fields.DBSimpleField), 
    385               ("COMMENT", fields.DBSimpleField), 
    386               ("REFERENCE", fields.DBReference), 
    387               ("PATHWAY", fields.DBPathway), 
    388               ("ORTHOLOGY", fields.DBSimpleField), 
    389               ("GENES", fields.DBSimpleField), 
    390               ("DBLINKS", fields.DBDBLinks) 
    391               ] 
    392      
     467    FIELDS = [ 
     468        ("ENTRY", fields.DBEntryField), 
     469        ("NAME", fields.DBNameField), 
     470        ("CLASS", fields.DBSimpleField), 
     471        ("SYSNAME", fields.DBSimpleField), 
     472        ("REACTION", fields.DBSimpleField), 
     473        ("ALL_REAC", fields.DBSimpleField), 
     474        ("SUBSTRATE", fields.DBSimpleField), 
     475        ("PRODUCT", fields.DBSimpleField), 
     476        ("COMMENT", fields.DBSimpleField), 
     477        ("REFERENCE", fields.DBReference), 
     478        ("PATHWAY", fields.DBPathway), 
     479        ("ORTHOLOGY", fields.DBSimpleField), 
     480        ("GENES", fields.DBSimpleField), 
     481        ("DBLINKS", fields.DBDBLinks) 
     482    ] 
     483 
    393484    MULTIPLE_FIELDS = ["REFERENCE"] 
    394      
    395 class Enzymes(DBDataBase): 
     485 
     486 
     487class Enzyme(DBDataBase): 
    396488    DB = "ec" 
    397489    ENTRY_TYPE = EnzymeEntry 
    398      
    399      
     490 
     491    def __init__(self): 
     492        DBDataBase.__init__(self) 
     493        self._keys = [d.entry_id for d in self.api.list("ec")] 
     494 
     495 
    400496@entry.entry_decorate 
    401497class OrthologyEntry(entry.DBEntry): 
    402     FIELDS = [("ENTRY", fields.DBEntryField), 
    403               ("NAME", fields.DBNameField), 
    404               ("CLASS", fields.DBSimpleField), 
    405               ("DBLINKS", fields.DBDBLinks), 
    406               ("GENES", fields.DBSimpleField), 
    407               ] 
    408      
     498    FIELDS = [ 
     499        ("ENTRY", fields.DBEntryField), 
     500        ("NAME", fields.DBNameField), 
     501        ("CLASS", fields.DBSimpleField), 
     502        ("DBLINKS", fields.DBDBLinks), 
     503        ("GENES", fields.DBSimpleField), 
     504    ] 
     505 
     506 
    409507class Orthology(DBDataBase): 
    410508    DB = "ko" 
    411509    ENTRY_TYPE = OrthologyEntry 
    412      
    413      
     510 
     511    def __init__(self): 
     512        DBDataBase.__init__(self) 
     513        self._keys = [d.entry_id for d in self.api.list("ko")] 
     514 
     515 
    414516@entry.entry_decorate 
    415517class PathwayEntry(entry.DBEntry): 
    416     FIELDS = [("ENTRY", fields.DBEntryField), 
    417               ("NAME", fields.DBNameField), 
    418               ("DESCRIPTION", fields.DBSimpleField), 
    419               ("CLASS", fields.DBSimpleField), 
    420               ("PATHWAY_MAP", fields.DBPathwayMapField), 
    421               ("DISEASE", fields.DBSimpleField), 
    422               ("DRUG", fields.DBSimpleField), 
    423               ("DBLINKS", fields.DBDBLinks), 
    424               ("ORGANISM", fields.DBSimpleField), 
    425               ("GENE", fields.DBGeneField), 
    426               ("ENZYME", fields.DBEnzymeField), 
    427               ("COMPOUND", fields.DBCompoundField), 
    428               ("REFERENCE", fields.DBReference), 
    429               ("REL_PATHWAY", fields.DBSimpleField), 
    430               ("KO_PATHWAY", fields.DBSimpleField), 
    431               ] 
    432      
     518    FIELDS = [ 
     519        ("ENTRY", fields.DBEntryField), 
     520        ("NAME", fields.DBNameField), 
     521        ("DESCRIPTION", fields.DBSimpleField), 
     522        ("CLASS", fields.DBSimpleField), 
     523        ("PATHWAY_MAP", fields.DBPathwayMapField), 
     524        ("MODULE", fields.DBSimpleField), 
     525        ("DISEASE", fields.DBSimpleField), 
     526        ("DRUG", fields.DBSimpleField), 
     527        ("DBLINKS", fields.DBDBLinks), 
     528        ("ORGANISM", fields.DBSimpleField), 
     529        ("GENE", fields.DBGeneField), 
     530        ("ENZYME", fields.DBEnzymeField), 
     531        ("COMPOUND", fields.DBCompoundField), 
     532        ("REFERENCE", fields.DBReference), 
     533        ("REL_PATHWAY", fields.DBSimpleField), 
     534        ("KO_PATHWAY", fields.DBSimpleField), 
     535    ] 
     536 
    433537    MULTIPLE_FIELDS = ["REFERENCE"] 
    434      
     538 
    435539    @property 
    436540    def gene(self): 
     
    439543        else: 
    440544            return None 
    441          
     545 
    442546        org = self.organism 
    443547        org_prefix = "" 
     
    447551                org_prefix = match[0] + ":" 
    448552        genes = [org_prefix + g for g in genes] 
    449         return genes  
    450      
    451 class Pathways(DBDataBase): 
     553        return genes 
     554 
     555 
     556class Pathway(DBDataBase): 
    452557    DB = "path" 
    453558    ENTRY_TYPE = PathwayEntry 
    454      
     559 
    455560    def __init__(self): 
    456561        DBDataBase.__init__(self) 
    457      
     562        self._keys = [d.entry_id for d in self.api.list("path")] 
  • _bioinformatics/obiKEGG/entry/__init__.py

    r1716 r1733  
    11""" 
    2 DBGET entry  
     2DBGET entry 
    33""" 
    44from __future__ import absolute_import 
  • _bioinformatics/obiKEGG/entry/parser.py

    r1716 r1733  
    11""" 
    2 A parser for DBGET entries 
    3   
     2A parser for DBGET database entries 
     3 
    44""" 
     5from StringIO import StringIO 
     6 
    57 
    68class DBGETEntryParser(object): 
    7     """ A DBGET entry parser (inspired by ``xml.dom.pulldom``) 
     9    r""" 
     10    A DBGET entry parser (inspired by ``xml.dom.pulldom``). 
     11 
     12    :: 
     13 
     14        >>> stream = StringIO("ENTRY foo\n" 
     15        ...                   "NAME  foo's name\n" 
     16        ...                   "  BAR A subsection of 'NAME'\n") 
     17        ... 
     18        >>> parser = DBGETEntryParser() 
     19        >>> for event, title, contents_part in parser.parse(stream): 
     20        ...    print parser.EVENTS[event], title, repr(contents_part) 
     21        ... 
     22        ENTRY_START None None 
     23        SECTION_START ENTRY 'foo\n' 
     24        SECTION_END ENTRY None 
     25        SECTION_START NAME "foo's name\n" 
     26        SUBSECTION_START BAR "A subsection of 'NAME'\n" 
     27        SUBSECTION_END BAR None 
     28        SECTION_END NAME None 
     29        ENTRY_END None None 
     30 
    831    """ 
     32    #: Entry start events 
    933    ENTRY_START = 0 
     34 
     35    #: Entry end event 
    1036    ENTRY_END = 1 
     37 
     38    #: Section start event 
    1139    SECTION_START = 2 
     40 
     41    #: Section end event 
    1242    SECTION_END = 3 
     43 
     44    #: Subsection start event 
    1345    SUBSECTION_START = 4 
     46 
     47    #: Subsection end event 
    1448    SUBSECTION_END = 5 
     49 
     50    #: Text element event 
    1551    TEXT = 6 
    16      
     52 
     53    EVENTS = ["ENTRY_START", "ENTRY_END", 'SECTION_START', 
     54              'SECTION_END', 'SUBSECTION_START', 'SUBSECTION_END', 
     55              'TEXT'] 
     56 
    1757    def __init__(self): 
    1858        pass 
    19      
     59 
    2060    def parse(self, stream): 
    2161        entry_offset = None 
    22         section_offset = None 
    2362        section_title = None 
    24         subsection_offset = None 
    2563        subsection_title = None 
    2664        textline_start = None 
    27          
     65 
    2866        for line in stream: 
    2967            startswith = line.startswith 
    30             # TODO: Reorder by frequency  
     68            # TODO: Reorder by frequency (for faster fallthrough) 
    3169            if startswith("ENTRY"): 
    3270                # Start parsing new entry 
     
    3775                yield (self.SECTION_START, title, rest) 
    3876                yield (self.SECTION_END, title, None) 
    39                  
     77 
    4078            elif startswith("///"): 
    4179                # End entry 
     
    4482                    yield (self.SUBSECTION_END, subsection_title, None) 
    4583                    subsection_title = None 
    46                     subsection_offset = None 
    47                      
     84 
    4885                if section_title is not None: 
    4986                    # End current section if any 
    5087                    yield (self.SECTION_END, section_title, None) 
    5188                    section_title = None 
    52                     subsection_offset = None 
    53                      
     89 
    5490                yield (self.ENTRY_END, None, None) 
    5591                entry_offset = None 
    5692                textline_start = None 
    57                  
     93 
    5894            elif not startswith(" "): 
    5995                # Start new section 
     
    6298                    yield (self.SUBSECTION_END, subsection_title, None) 
    6399                    subsection_title = None 
    64                     subsection_offset = None 
    65                      
     100 
    66101                if section_title is not None: 
    67102                    # End current section if any 
    68103                    yield (self.SECTION_END, section_title, None) 
    69104                    section_title = None 
    70                     subsection_offset = None 
     105 
    71106                title, rest = self._partition_section_title(line) 
    72                 section_offset = len(line) - len(rest) 
    73107                section_title = title 
    74108                yield (self.SECTION_START, section_title, rest) 
    75                  
     109 
    76110            elif startswith(textline_start): 
    77111                # A line of text 
    78112                # TODO: pass the current subsection/section title 
    79113                yield (self.TEXT, None, line[entry_offset:]) 
    80                  
     114 
    81115            elif startswith(" "): 
    82116                # Start a new subsection 
     
    85119                    yield (self.SUBSECTION_END, subsection_title, None) 
    86120                title, rest = self._partition_subsection_title(line) 
    87                 subsection_offset = len(line) - len(rest) 
    88121                subsection_title = title 
    89122                yield (self.SUBSECTION_START, subsection_title, rest) 
    90                  
     123 
    91124        # Close any remaining sections/entries 
    92125        if subsection_title is not None: 
     
    96129        if entry_offset is not None: 
    97130            yield (self.ENTRY_END, None, None) 
    98      
     131 
    99132    def parse_string(self, string): 
    100         from StringIO import StringIO 
    101133        return self.parse(StringIO(string)) 
    102      
     134 
    103135    def _partition_section_title(self, line): 
    104         """ Split the section title from the rest of the line 
     136        """ 
     137        Split the section title from the rest of the line 
    105138        """ 
    106139        title, rest = line.split(" ", 1) 
    107140        rest = rest.lstrip(" ") 
    108141        return title, rest 
    109      
     142 
    110143    def _partition_subsection_title(self, line): 
    111         """ Split the subsection title from the rest of the line 
     144        """ 
     145        Split the subsection title from the rest of the line 
    112146        """ 
    113147        line = line.lstrip(" ") 
    114148        return self._partition_section_title(line) 
    115      
  • _bioinformatics/obiKEGG/pathway.py

    r1716 r1733  
    1616from . import conf 
    1717from . import caching 
     18from . import api 
    1819 
    1920from Orange.utils import deprecated_attribute 
    20      
     21 
     22 
    2123def cached_method(func, cache_name="_cached_method_cache", store=None): 
    2224    def wrapper(self, *args, **kwargs): 
     
    275277        """ 
    276278        return self._get_image_filename() 
    277      
     279 
    278280    @classmethod 
    279281    def list(cls, organism): 
    280         from . import api  
    281282        kegg = api.CachedKeggApi() 
    282283        return kegg.list_pathways(organism) 
    283      
  • _bioinformatics/obiKEGG/service.py

    r1716 r1733  
    11""" 
    2 SOAP service client. Needs suds library. 
    3   
     2 
    43""" 
    54from __future__ import absolute_import 
     
    76KEGG_WDSL = "http://soap.genome.jp/KEGG.wsdl" 
    87 
    9 import urllib2 
     8REST_API = "http://rest.kegg.jp/" 
    109 
    11 def suds_service(): 
    12     """ Return an suds service object with kegg api service methods. 
    13      
    14     >>> service = web_service() 
    15     >>> service.list_databases() 
    16     [(Definition){... 
    1710 
     11def slumber_service(): 
    1812    """ 
    19     from suds.client import Client 
    20     client = Client(KEGG_WDSL) 
    21     return client.service 
     13    Return a rest based service using `slumber` package 
     14    """ 
     15    import slumber 
     16    if not hasattr(slumber_service, "_cached"): 
     17        slumber_service._cached = slumber.API(REST_API) 
     18    return slumber_service._cached 
    2219 
    23 def suds_service_with_requests(): 
    24     import StringIO 
    25      
    26     from suds.client import Client 
    27     from suds.transport import Transport, TransportError 
    28     from suds.properties import Unskin 
    29      
    30     import requests 
    31  
    32     class RequestsResponse(object): 
    33         pass 
    34  
    35     class RequestsTransport(Transport): 
    36         def __init__(self, **kwargs): 
    37             Transport.__init__(self) 
    38             Unskin(self.options).update(kwargs) 
    39             self.cookies = {} 
    40              
    41         def send(self, request): 
    42             result = None 
    43             url = request.url 
    44             message = request.message 
    45             headers = request.headers 
    46             # This does not seem to work, every request seems 
    47             # to open a new connection 
    48             headers["Connection"] = "Keep-Alive" 
    49             try: 
    50                 response = requests.post(url, data=message,  
    51                                          headers=headers, 
    52                                          cookies=self.cookies) 
    53                      
    54                 self.proxy = self.options.proxy 
    55                 response.raise_for_status() 
    56                  
    57                 self.cookies.update(response.cookies) 
    58                 result = RequestsResponse() 
    59                 result.code = response.status_code 
    60                 result.headers = response.headers 
    61                 result.message = response.raw.read() 
    62                 return result 
    63                  
    64             except urllib2.HTTPError, e: 
    65                 if e.code in [202, 204]: 
    66                     return None 
    67                 else: 
    68                     raise TransportError(str(e), e.code, e.fp) 
    69                  
    70         def open(self, request): 
    71             url = request.url 
    72             message = request.message 
    73             try: 
    74                 response = requests.get(url) 
    75                 self.proxy = self.options.proxy 
    76                  
    77                 response.raise_for_status() 
    78                 return StringIO.StringIO(response.raw.read()) 
    79             except urllib2.HTTPError, e: 
    80                 raise TransportError(str(e), e.code, e.fp) 
    81              
    82     transport = RequestsTransport() 
    83     client = Client(KEGG_WDSL, transport=transport) 
    84     return client.service 
    85      
    86 def SOAPy_service(): 
    87     import SOAPy 
    8820 
    8921from . import conf 
    9022 
    91 default_service = suds_service 
    92 web_service = suds_service 
     23default_service = slumber_service 
    9324 
    94 if conf.params["service.transport"] == "requests": 
    95     try: 
    96         import requests     
    97         web_service = suds_service_with_requests 
    98     except ImportError: 
    99         import warnings 
    100         warnings.warn("requests package not installed.") 
    101          
    102 elif conf.params["service.transport"] == "urllib2": 
    103     pass 
    104  
    105  
     25web_service = slumber_service 
  • _bioinformatics/obiKEGG/types.py

    r1716 r1733  
    66from datetime import datetime 
    77from collections import namedtuple 
     8from operator import methodcaller 
    89 
    910Definition = namedtuple( 
    10     "Definition", ["entry_id", 
    11                    "definition" 
    12                    ]) 
     11    "Definition", 
     12    ["entry_id", 
     13     "definition"] 
     14) 
     15 
    1316 
    1417def _Definition_from_items(items): 
     
    2427    return Definition(**dict(items_list)) 
    2528 
     29 
     30def _Definition_from_str(text): 
     31    """ 
     32    Return a `Definition` item by parsing a tab separated string `text` 
     33    i.e. text must be of the form '<entry_id>\t<definition>' 
     34 
     35    """ 
     36    return Definition(*text.split("\t", 1)) 
     37 
     38 
    2639Definition.from_items = staticmethod(_Definition_from_items) 
    27      
     40Definition.from_str = staticmethod(_Definition_from_str) 
     41 
     42 
     43OrganismSummary = namedtuple( 
     44    "OrganismSummary", 
     45    ["entry_id", 
     46     "org_code", 
     47     "name", 
     48     "lineage"], 
     49) 
     50 
     51 
     52def OrganismSummary_from_str(string): 
     53    return OrganismSummary(*string.split("\t")) 
     54 
     55OrganismSummary.from_str = staticmethod(OrganismSummary_from_str) 
     56 
     57 
    2858BInfo = namedtuple( 
    29     'BInfo', ["entry_id", 
    30               "definition", 
    31               "name", 
    32               "release", 
    33               "curator", 
    34               "contents", 
    35               "last_update", 
    36               "supported_formats" 
    37               ]) 
     59    'BInfo', 
     60    ["entry_id", 
     61    "definition", 
     62    "name", 
     63    "release", 
     64    "curator", 
     65    "contents", 
     66    "last_update", 
     67    "supported_formats"] 
     68) 
     69 
    3870 
    3971def _BInfo_from_text(text): 
    40     """ Parse the return string from binfo into a new BInfo instance. 
     72    """ Parse the return string from info into a new BInfo instance. 
    4173    """ 
    4274    lines = text.splitlines() 
    4375    name, definition = lines[0].split(" ", 1) 
    4476    definition = definition.strip() 
    45      
    4677    entry_id, release = lines[1].split(" ", 1) 
    4778    _, release = release.strip().split(" ", 1) 
    4879    curator = lines[2].strip() 
    49     contents = lines[3].strip() 
    50     _, last_update = lines[4].strip().split(":",1) 
    51     last_update = datetime.strptime(last_update.strip(), "%y/%m/%d").date() 
    52     supported_formats = lines[5].strip() 
     80    contents = "\n".join(map(methodcaller("strip"), lines[3:])) 
     81 
    5382    return BInfo(entry_id, definition, name, release, curator, 
    54                  contents, last_update, supported_formats) 
     83                 contents, None, None) 
    5584 
    5685BInfo.from_text = staticmethod(_BInfo_from_text) 
     86 
     87 
     88Link = namedtuple("Link", ["entry_id1", "entry_id2"]) 
    5789 
    5890 
  • _bioinformatics/widgets/OWKEGGPathwayBrowser.py

    r1726 r1733  
    66""" 
    77 
    8 from __future__ import absolute_import, with_statement  
    9  
    10 if __name__ == "__main__":  
    11     __package__ = "Orange.bio.widgets" 
     8from __future__ import absolute_import, with_statement 
    129 
    1310import sys 
     11import gc 
    1412from collections import defaultdict 
    1513import webbrowser 
     
    310308        self.setEnabled(False) 
    311309        QTimer.singleShot(100, self.UpdateOrganismComboBox) 
    312          
    313          
     310 
    314311    def UpdateOrganismComboBox(self): 
    315312        # First try to import suds 
    316313        try: 
    317             import suds 
     314            import slumber 
    318315        except ImportError: 
    319316            QMessageBox.warning(self, 
    320                 "'suds' library required.", 
    321                 '<p>Please install \ 
    322 <a href="http://pypi.python.org/pypi/suds">suds</a> library \ 
    323 to use KEGG Pathways widget.</p>' 
    324                 ) 
    325              
     317                "'slumber' library required.", 
     318                '<p>Please install ' 
     319                '<a href="http://pypi.python.org/pypi/slumber">slumber</a> ' 
     320                'library to use KEGG Pathways widget.</p>' 
     321            ) 
     322 
    326323        try: 
    327324            genome = obiKEGG.KEGGGenome() 
    328             all_codes = list(genome) 
    329              
    330             self.allOrganismCodes = genome  
    331      
     325 
     326            self.allOrganismCodes = genome 
     327 
    332328            essential = genome.essential_organisms() 
    333329            common = genome.common_organisms() 
    334330            common = [c for c in common if c not in essential] 
    335              
     331 
     332            # TODO: Add option to specify additional organisms not 
     333            # in the common list. 
     334 
    336335            self.infoLabel.setText("Fetching organism definitions\n") 
    337              
    338             pb = OWGUI.ProgressBar(self, len(essential + common)) 
     336 
     337            keys = map(genome.org_code_to_entry_key, essential + common) 
     338 
     339            self.progressBarInit() 
     340            genome.pre_cache(keys, progress_callback=self.progressBarSet) 
     341            self.progressBarFinished() 
     342 
    339343            codes = [] 
    340             for i, code in enumerate(essential + common): 
    341                 codes.append((code, genome[code].definition)) 
    342                 pb.advance() 
    343             pb.finish() 
    344             self.organismCodes = codes 
    345              
    346             items = [desc for code, desc in self.organismCodes] 
    347              
    348             self.organismCodes = [code for code, desc in self.organismCodes] 
    349  
    350             # TODO: Add option to specify additional organisms not  
    351             # in the common list. 
    352  
     344            for code, key in zip(essential + common, keys): 
     345                codes.append((code, genome[key].definition)) 
     346 
     347            items = [desc for code, desc in codes] 
     348 
     349            self.organismCodes = [code for code, desc in codes] 
    353350            self.organismComboBox.addItems(items) 
     351 
    354352        finally: 
    355353            self.setEnabled(True) 
    356354            self.infoLabel.setText("No data on input\n") 
    357             self.signalManager.freeze(self).pop() #setFreeze(0) 
     355            self.signalManager.freeze(self).pop() 
    358356 
    359357    def Clear(self): 
     358        """ 
     359        Clear the widget state. 
     360        """ 
    360361        self.infoLabel.setText("No data on input\n") 
    361362        self.listView.clear() 
    362363        self.ClearPathway() 
    363          
     364 
    364365        self.send("Selected Examples", None) 
    365366        self.send("Unselected Examples", None) 
    366          
     367 
    367368    def ClearPathway(self): 
    368369        self.pathwayView.SetPathway(None) 
     
    419420         
    420421        self.geneAttrCombo.addItems([var.name for var in self.geneAttrCandidates]) 
    421              
     422 
    422423    def UpdateListView(self): 
    423424        self.bestPValueItem = None 
     
    425426        if not self.data: 
    426427            return 
     428 
    427429        allPathways = self.org.pathways() 
    428430        allRefPathways = obiKEGG.pathways("map") 
    429 #        self.progressBarFinished() 
     431 
    430432        items = [] 
    431433        self.progressBarInit() 
     
    434436                                progress_callback=self.progressBarSet) 
    435437        self.progressBarFinished() 
     438 
     439        org_code = self.organismCodes[min(self.organismIndex, 
     440                                          len(self.organismCodes)-1)] 
     441 
    436442        if self.showOrthology: 
    437443            self.koOrthology = obiKEGG.KEGGBrite("ko00001") 
    438444            self.listView.setRootIsDecorated(True) 
    439445            path_ids = set([s[-5:] for s in self.pathways.keys()]) 
     446 
    440447            def _walkCollect(koEntry): 
    441448                num = koEntry.title[:5] if koEntry.title else None 
    442                 if num  in path_ids: 
    443                     return [koEntry] + reduce(lambda li,c:li+_walkCollect(c), [child for child in koEntry.entries], []) 
     449                if num in path_ids: 
     450                    return [koEntry] + reduce(lambda li, c:li + _walkCollect(c), [child for child in koEntry.entries], []) 
    444451                else: 
    445                     c = reduce(lambda li,c:li+_walkCollect(c), [child for child in koEntry.entries], []) 
     452                    c = reduce(lambda li, c: li + _walkCollect(c), 
     453                               [child for child in koEntry.entries], []) 
    446454                    return c + (c and [koEntry] or []) 
    447             allClasses = reduce(lambda li1, li2: li1+li2, [_walkCollect(c) for c in self.koOrthology], []) 
     455 
     456            allClasses = reduce(lambda li1, li2: li1 + li2, 
     457                                [_walkCollect(c) for c in self.koOrthology], []) 
     458 
    448459            def _walkCreate(koEntry, lvItem): 
    449460                item = QTreeWidgetItem(lvItem) 
    450                 id = "path:"+self.organismCodes[min(self.organismIndex, len(self.organismCodes)-1)] + koEntry.title[:5] 
    451                 p = kegg_pathways.get_entry(id) 
     461                id = "path:" + org_code + koEntry.title[:5] 
     462 
    452463                if koEntry.title[:5] in path_ids: 
     464                    p = kegg_pathways.get_entry(id) 
    453465                    if p is None: 
    454                         # In case the genesets still have obsolete entries  
     466                        # In case the genesets still have obsolete entries 
    455467                        name = koEntry.title 
    456468                    else: 
     
    459471                    item.setText(0, name) 
    460472                    item.setText(1, "%.5f" % p_value) 
    461                     item.setText(2, "%i of %i" %(len(genes), len(self.genes))) 
    462                     item.setText(3, "%i of %i" %(ref, len(self.referenceGenes))) 
     473                    item.setText(2, "%i of %i" % (len(genes), len(self.genes))) 
     474                    item.setText(3, "%i of %i" % (ref, len(self.referenceGenes))) 
    463475                    item.pathway_id = id if p is not None else None 
    464476                else: 
    465                     item.setText(0, p.name if id in allPathways else koEntry.title) 
     477                    if id in allPathways: 
     478                        text = kegg_pathways.get_entry(id).name 
     479                    else: 
     480                        text = koEntry.title 
     481                    item.setText(0, text) 
     482 
    466483                    if id in allPathways: 
    467484                        item.pathway_id = id 
     
    470487                    else: 
    471488                        item.pathway_id = None 
    472                  
     489 
    473490                for child in koEntry.entries: 
    474491                    if child in allClasses: 
    475492                        _walkCreate(child, item) 
    476              
     493 
    477494            for koEntry in self.koOrthology: 
    478495                if koEntry in allClasses: 
    479496                    _walkCreate(koEntry, self.listView) 
    480                      
     497 
    481498            self.listView.update() 
    482499        else: 
    483500            self.listView.setRootIsDecorated(False) 
    484501            pathways = self.pathways.items() 
    485             pathways.sort(lambda a,b:cmp(a[1][1], b[1][1])) 
     502            pathways.sort(lambda a, b: cmp(a[1][1], b[1][1])) 
     503 
    486504            for id, (genes, p_value, ref) in pathways: 
    487505                item = QTreeWidgetItem(self.listView) 
    488506                item.setText(0, kegg_pathways.get_entry(id).name) 
    489507                item.setText(1, "%.5f" % p_value) 
    490                 item.setText(2, "%i of %i" %(len(genes), len(self.genes))) 
    491                 item.setText(3, "%i of %i" %(ref, len(self.referenceGenes))) 
     508                item.setText(2, "%i of %i" % (len(genes), len(self.genes))) 
     509                item.setText(3, "%i of %i" % (ref, len(self.referenceGenes))) 
    492510                item.pathway_id = id 
    493511                items.append(item) 
    494                  
     512 
    495513        self.bestPValueItem = items and items[0] or None 
    496514        self.listView.expandAll() 
     
    760778    def queuedInvoke(self, func): 
    761779        func() 
    762          
     780 
    763781    def progressBarSet(self, value): 
    764 #        print "Enter" 
    765782        if not getattr(self, "_in_progress_update", False): 
    766783            self._in_progress_update = True 
     
    769786            finally: 
    770787                self._in_progress_update = False 
    771 #        else: 
    772 #            print "=====" 
    773          
    774 #        print "Exit" 
    775      
     788 
    776789    def onDeleteWidget(self): 
    777790        """ Called before the widget is removed from the canvas. 
    778791        """ 
    779792        self.org = None 
    780         import gc 
    781         gc.collect() # Force collection 
     793        gc.collect()  # Force collection 
    782794         
    783795    def UpdateToLatestPathways(self): 
     
    812824                 for (id, genes, ref), p_val in zip(result_sets, p_values)] 
    813825                ) 
    814      
    815 if __name__=="__main__": 
     826 
     827if __name__ == "__main__": 
    816828    app = QApplication(sys.argv) 
    817829    data = orange.ExampleTable("brown-selected.tab") 
    818830    w = OWKEGGPathwayBrowser() 
    819831    w.UpdateOrganismComboBox() 
    820 ##    app.setMainWidget(w) 
    821832    w.show() 
    822833    w.SetData(orange.ExampleTable(data[:])) 
    823834    QTimer.singleShot(10, w.handleNewSignals) 
     835 
    824836    app.exec_() 
    825837    w.saveSettings() 
  • setup.py

    r1730 r1733  
    9090    ), 
    9191    'KEGG': ( 
    92         'suds' 
     92        'slumber >= 0.4' 
    9393    ) 
    9494 
Note: See TracChangeset for help on using the changeset viewer.