Changeset 1767:214b1db4e31a in orange-bioinformatics


Ignore:
Timestamp:
04/30/13 12:47:43 (12 months ago)
Author:
Ales Erjavec <ales.erjavec@…>
Branch:
default
Message:

obiGO code style fixes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • _bioinformatics/obiGO.py

    r1716 r1767  
    1 """obiGO is a Gene Ontology (GO) Handling Library. 
    2  
    31""" 
     2`obiGO` is a Gene Ontology (GO) Handling Library. 
     3 
     4""" 
    45 
    56from __future__ import absolute_import 
     7import os 
     8import sys 
     9import tarfile 
     10import gzip 
     11import re 
     12import cPickle 
     13import shutil 
     14import urllib2 
     15import warnings 
     16import copy 
    617 
    718from urllib import urlretrieve 
    819from gzip import GzipFile 
    9 import tarfile 
    10 import gzip 
    11 import shutil 
    12 import sys, os 
    13 import re, cPickle 
    1420from datetime import datetime 
    1521from collections import defaultdict 
    1622 
    1723from Orange.orng import orngEnviron 
     24from Orange.orng import orngServerFiles 
     25from Orange.orng import orngMisc 
    1826 
    1927from . import obiProb, obiGene 
    2028 
    21 try: 
    22     from Orange.orng import orngServerFiles 
    23     default_database_path = os.path.join(orngServerFiles.localpath(), "GO") 
    24 except Exception: 
    25     default_database_path = os.curdir 
     29default_database_path = os.path.join(orngServerFiles.localpath(), "GO") 
     30 
    2631 
    2732_CVS_REVISION_RE = re.compile(r"^(rev)?\d+\.\d+$") 
    2833 
    2934evidenceTypes = { 
    30 ##Experimental 
     35# Experimental 
    3136    'EXP': 'Inferred from Experiment', 
    3237    'IDA': 'Inferred from Direct Assay', 
    33     'IPI': 'Inferred from Physical Interaction', ## [with <database:protein_name>]', 
     38    'IPI': 'Inferred from Physical Interaction',  # [with <database:protein_name>]', 
    3439    'IMP': 'Inferred from Mutant Phenotype', 
    35     'IGI': 'Inferred from Genetic Interaction', ## [with <database:gene_symbol[allele_symbol]>]', 
     40    'IGI': 'Inferred from Genetic Interaction',  # [with <database:gene_symbol[allele_symbol]>]', 
    3641    'IEP': 'Inferred from Expression Pattern', 
    37 ##Computational Analysis Evidence Codes 
    38     'ISS': 'Inferred from Sequence Similarity', ## [with <database:sequence_id>] ', 
     42# Computational Analysis Evidence Codes 
     43    'ISS': 'Inferred from Sequence Similarity',  # [with <database:sequence_id>] ', 
    3944    'ISA': 'Inferred from Sequence Alignment', 
    4045    'ISO': 'Inferred from Sequence Orthology', 
     
    4247    'IGC': 'Inferred from Genomic Context', 
    4348    'RCA': 'Inferred from Reviewed Computational Analysis', 
    44 ##Author Statement Evidence Codes 
     49# Author Statement Evidence Codes 
    4550    'TAS': 'Traceable author statement', 
    4651    'NAS': 'Non-traceable author statement', 
    47 ##Curatorial Statement Evidence Codes 
     52# Curatorial Statement Evidence Codes 
    4853    'IC': 'Inferred by curator', 
    4954    'ND': 'No biological data available', 
    50 ##Computationally-assigned Evidence Codes 
    51     'IEA': 'Inferred from electronic annotation', ## [to <database:id>]', 
    52 ##Obsolete Evidence Codes 
     55# Computationally-assigned Evidence Codes 
     56    'IEA': 'Inferred from electronic annotation',  # [to <database:id>]', 
     57# Obsolete Evidence Codes 
    5358    'NR': 'Not Recorded(Obsolete)' 
    5459} 
    55 ##evidenceDict={"IMP":1, "IGI":2, "IPI":4, "ISS":8, "IDA":16, "IEP":32, "IEA":64, 
    56 ##              "TAS":128, "NAS":256, "ND":512, "IC":1024, "RCA":2048, "IGC":4096, "RCA":8192, "NR":16384} 
    57  
    58 evidenceDict=defaultdict(int, [(e, 2**i) for i, e in enumerate(evidenceTypes.keys())]) 
     60 
     61 
     62evidenceDict = defaultdict(int, [(e, 2 ** i) for i, e in 
     63                                enumerate(evidenceTypes.keys())]) 
    5964 
    6065evidenceTypesOrdered = [ 
     
    6570'IGI', 
    6671'IEP', 
    67 ##Computational Analysis Evidence Codes 
     72# Computational Analysis Evidence Codes 
    6873'ISS', 
    6974'ISA', 
     
    7277'IGC', 
    7378'RCA', 
    74 ##Author Statement Evidence Codes 
     79# Author Statement Evidence Codes 
    7580'TAS', 
    7681'NAS', 
    77 ##Curatorial Statement Evidence Codes 
     82# Curatorial Statement Evidence Codes 
    7883'IC', 
    7984'ND', 
    80 ##Computationally-assigned Evidence Codes 
     85# Computationally-assigned Evidence Codes 
    8186'IEA', 
    82 ##Obsolete Evidence Codes 
     87# Obsolete Evidence Codes 
    8388'NR' 
    8489] 
    8590 
    86 multiplicitySet=set(["alt_id","is_a","subset","synonym","related_synonym", 
    87                      "exact_synonym","broad_synonym","narrow_synonym", 
    88                      "xref_analog","xref_unknown","relationship"]) 
     91multiplicitySet = set( 
     92    ["alt_id", "is_a", "subset", "synonym", "related_synonym", 
     93     "exact_synonym", "broad_synonym", "narrow_synonym", 
     94     "xref_analog", "xref_unknown", "relationship"]) 
    8995 
    9096multipleTagSet = multiplicitySet 
    9197 
    92 annotationFields=["DB","DB_Object_ID","DB_Object_Symbol","Qualifier","GO_ID", 
    93                   "DB_Reference","Evidence_Code","With_From","Aspect", 
    94                   "DB_Object_Name","DB_Object_Synonym","DB_Object_Type", 
    95                   "Taxon","Date","Assigned_by"] 
    96  
    97 annotationFieldsDict={"DB":0, 
    98                       "DB_Object_ID":1, 
    99                       "DB_Object_Symbol":2, 
    100                       "Qualifier":3, 
    101                       "GO_ID":4, 
    102                       "GO ID":4, 
    103                       "GOID":4, 
    104                       "DB_Reference":5, 
    105                       "DB:Reference":5, 
    106                       "Evidence_Code":6, 
    107                       "Evidence Code":6, 
    108                       "Evidence_code":6, #compatibility with  older revisions 
    109                       "With_or_From":7, 
    110                       "With (or) From":7, 
    111                       "Aspect":8, 
    112                       "DB_Object_Name":9, 
    113                       "DB_Object_Synonym":10, 
    114                       "DB_Object_Type":11, 
    115                       "taxon":12, 
    116                       "Date":13, 
    117                       "Assigned_by":14}     
     98annotationFields = [ 
     99    "DB", "DB_Object_ID", "DB_Object_Symbol", "Qualifier", "GO_ID", 
     100    "DB_Reference", "Evidence_Code", "With_From", "Aspect", "DB_Object_Name", 
     101    "DB_Object_Synonym", "DB_Object_Type", "Taxon", "Date", "Assigned_by"] 
     102 
     103annotationFieldsDict = { 
     104    "DB": 0, 
     105    "DB_Object_ID": 1, 
     106    "DB_Object_Symbol": 2, 
     107    "Qualifier": 3, 
     108    "GO_ID": 4, 
     109    "GO ID": 4, 
     110    "GOID": 4, 
     111    "DB_Reference": 5, 
     112    "DB:Reference": 5, 
     113    "Evidence_Code": 6, 
     114    "Evidence Code": 6, 
     115    "Evidence_code": 6,  # compatibility with  older revisions 
     116    "With_or_From": 7, 
     117    "With (or) From": 7, 
     118    "Aspect": 8, 
     119    "DB_Object_Name": 9, 
     120    "DB_Object_Synonym": 10, 
     121    "DB_Object_Type": 11, 
     122    "taxon": 12, 
     123    "Date": 13, 
     124    "Assigned_by": 14 
     125} 
    118126 
    119127builtinOBOObjects = [""" 
     
    160168definition: Indicates that a term is the intersection of several others [OBO:defs]"""] 
    161169 
     170 
    162171class OBOObject(object): 
    163     """ Represents a generic OBO object (e.g. Term, Typedef, Instance, ...) 
     172    """Represents a generic OBO object (e.g. Term, Typedef, Instance, ...) 
    164173    Example: 
     174 
    165175    >>> OBOObject(r"[Term]\nid: FOO:001\nname: bar", ontology) 
     176 
    166177    """ 
    167178    _INTERN_TAGS = ["id", "name", "namespace", "alt_id", "is_a"] 
     179 
    168180    def __init__(self, stanza=None, ontology=None): 
    169181        self.ontology = ontology 
     
    203215        if "def" in self.__dict__: 
    204216            self.__dict__["def_"] = self.__dict__["def"] 
    205          
    206217 
    207218    def GetRelatedObjects(self): 
    208         """ Return a list of tuple pairs where the first element is relationship 
    209         typeId and the second id of object to whom the relationship applys to. 
    210         """ 
    211         ##TODO: add other defined Typedef ids 
     219        """Return a list of tuple pairs where the first element is relationship 
     220        typeId and the second id of object to whom the relationship applies to. 
     221 
     222        """ 
     223        # TODO: add other defined Typedef ids 
    212224        typeIds = [intern("is_a")] 
    213         result = [(typeId, id) for typeId in typeIds for id in self.values.get(typeId, [])]  
    214         result = result + [tuple(map(intern, r.split(None, 1))) for r in self.values.get("relationship", [])] 
     225        result = [(typeId, id) for typeId in typeIds 
     226                  for id in self.values.get(typeId, [])] 
     227        result = result + [tuple(map(intern, r.split(None, 1))) 
     228                           for r in self.values.get("relationship", [])] 
    215229        return result 
    216230 
     
    238252        for typeId, id in self.relatedTo: 
    239253            yield (typeId, self.ontology[id]) 
    240          
     254 
     255 
    241256class Term(OBOObject): 
    242257    pass 
    243258 
     259 
    244260class Typedef(OBOObject): 
    245261    pass 
    246262 
     263 
    247264class Instance(OBOObject): 
    248265    pass 
    249          
     266 
     267 
    250268class Ontology(object): 
    251269    """ Ontology is the main class representing a gene ontology. 
    252      
     270 
    253271    Example:: 
    254272        >>> ontology = Ontology("my_gene_ontology.obo") 
    255          
     273 
    256274    """ 
    257275    version = 1 
     276 
    258277    def __init__(self, file=None, progressCallback=None, rev=None): 
    259278        """ Initialize the ontology from file (if `None` the default gene 
    260279        ontology will be loaded). The optional `progressCallback` will be 
    261280        called with a single argument to report on the progress. 
    262          
     281 
    263282        """ 
    264283        self.terms = {} 
     
    268287        if isinstance(file, basestring): 
    269288            self.ParseFile(file, progressCallback) 
    270              
     289 
    271290        elif rev is not None: 
    272291            if not _CVS_REVISION_RE.match(rev): 
     
    274293            if rev.startswith("rev"): 
    275294                rev = rev[3:] 
    276             pc = lambda v: progressCallback(v/2.0) \ 
     295            pc = lambda v: progressCallback(v / 2.0) \ 
    277296                 if progressCallback else None 
    278             filename = os.path.join(default_database_path, "gene_ontology_edit@rev%s.obo" % rev) 
     297            filename = os.path.join(default_database_path, 
     298                                    "gene_ontology_edit@rev%s.obo" % rev) 
    279299            if not os.path.exists(filename): 
    280300                self.DownloadOntologyAtRev(rev, filename, pc) 
    281             self.ParseFile(filename, lambda v: progressCallback(v/2.0 + 50) \ 
     301            self.ParseFile(filename, lambda v: progressCallback(v / 2.0 + 50) \ 
    282302                                     if progressCallback else None) 
    283303        else: 
    284304            fool = self.Load(progressCallback) 
    285             self.__dict__ = fool.__dict__ ## A fool and his attributes are soon parted 
     305            # A fool and his attributes are soon parted 
     306            self.__dict__ = fool.__dict__ 
    286307 
    287308    @classmethod 
     
    291312        'gene_ontology'. If not found it will download it. 
    292313        """ 
    293         filename = os.path.join(default_database_path, "gene_ontology_edit.obo.tar.gz") 
     314        filename = os.path.join(default_database_path, 
     315                                "gene_ontology_edit.obo.tar.gz") 
    294316        if not os.path.isfile(filename) and not os.path.isdir(filename): 
    295             from Orange.orng import orngServerFiles 
    296317            orngServerFiles.download("GO", "gene_ontology_edit.obo.tar.gz") 
    297318        try: 
    298319            return cls(filename, progressCallback=progressCallback) 
    299320        except (IOError, OSError), ex: 
    300             print ex 
    301             raise Exception, "Could not locate ontology file" 
    302          
     321            raise Exception("Could not locate ontology file") 
     322 
    303323    def ParseFile(self, file, progressCallback=None): 
    304324        """ Parse the file. file can be a filename string or an open filelike 
     
    315335        else: 
    316336            f = file 
    317          
     337 
    318338        data = f.readlines() 
    319339        data = "".join([line for line in data if not line.startswith("!")]) 
    320340        self.header = data[: data.index("[Term]")] 
    321         c=re.compile("\[.+?\].*?\n\n", re.DOTALL) 
    322         data=c.findall(data) 
    323  
    324         from Orange.orng import orngMisc 
     341        c = re.compile("\[.+?\].*?\n\n", re.DOTALL) 
     342        data = c.findall(data) 
     343 
    325344        milestones = orngMisc.progressBarMilestones(len(data), 90) 
    326345        for i, block in enumerate(builtinOBOObjects + data): 
     
    335354                self.instances[instance.id] = instance 
    336355            if progressCallback and i in milestones: 
    337                 progressCallback(90.0*i/len(data)) 
    338          
     356                progressCallback(90.0 * i / len(data)) 
     357 
    339358        self.aliasMapper = {} 
    340359        self.reverseAliasMapper = defaultdict(set) 
     
    344363                self.terms[parent].relatedTo.add((typeId, id)) 
    345364            try: 
    346                 self.aliasMapper.update([(alt_id, id) for alt_id in term.alt_id]) 
     365                self.aliasMapper.update([(alt_id, id) 
     366                                         for alt_id in term.alt_id]) 
    347367                self.reverseAliasMapper[id].union_update(term.alt_id) 
    348368            except AttributeError: 
    349369                pass 
    350370            if progressCallback and i in milestones: 
    351                 progressCallback(90.0 + 10.0*i/len(self.terms)) 
     371                progressCallback(90.0 + 10.0 * i / len(self.terms)) 
    352372 
    353373    def GetDefinedSlimsSubsets(self): 
    354374        """ Return a list of defined subsets. 
    355375        """ 
    356         return [line.split()[1] for line in self.header.splitlines() if line.startswith("subsetdef:")] 
     376        return [line.split()[1] for line in self.header.splitlines() 
     377                if line.startswith("subsetdef:")] 
    357378 
    358379    def SetSlimsSubset(self, subset): 
     
    361382        """ 
    362383        if type(subset) == str: 
    363             self.slimsSubset = [id for id, term in self.terms.items() if subset in getattr(term, "subset", set())] 
     384            self.slimsSubset = [id for id, term in self.terms.items() 
     385                                if subset in getattr(term, "subset", set())] 
    364386        else: 
    365387            self.slimsSubset = set(subset) 
    366388 
    367389    def GetSlimsSubset(self, subset): 
    368         return [id for id, term in self.terms.items() if subset in getattr(term, "subset", set())] 
     390        return [id for id, term in self.terms.items() 
     391                if subset in getattr(term, "subset", set())] 
    369392 
    370393    def GetSlimTerms(self, termId): 
     
    380403                slims.add(term) 
    381404            else: 
    382                 queue.update(set(id for typeId, id in self[term].related) - visited) 
     405                queue.update(set(id for typeId, id in self[term].related) - 
     406                             visited) 
    383407        return slims 
    384408 
     
    392416            term = queue.pop() 
    393417            visited.add(term) 
    394             queue.update(set(id for typeId, id in self[term].related) - visited) 
     418            queue.update(set(id for typeId, id in self[term].related) - 
     419                         visited) 
    395420        return visited 
    396421 
     
    404429            term = queue.pop() 
    405430            visited.add(term) 
    406             queue.update(set(id for typeId, id in self[term].relatedTo) - visited) 
     431            queue.update(set(id for typeId, id in self[term].relatedTo) - 
     432                         visited) 
    407433        return visited 
    408434 
     
    412438        """ 
    413439        if term not in cache_: 
    414             cache_[term] = min([self.GetTermDepth(parent) + 1 for typeId, parent in self[term].related] or [1]) 
     440            cache_[term] = min([self.GetTermDepth(parent) + 1 
     441                                for typeId, parent in self[term].related] or 
     442                               [1]) 
    415443        return cache_[term] 
    416444 
     
    435463    @staticmethod 
    436464    def DownloadOntology(file, progressCallback=None): 
    437         tFile = tarfile.open(file, "w:gz") if isinstance(file, basestring) else file 
     465        tFile = tarfile.open(file, "w:gz") if isinstance(file, basestring) \ 
     466                else file 
    438467        tmpDir = os.path.join(orngEnviron.bufferDir, "tmp_go/") 
    439468        try: 
     
    441470        except Exception: 
    442471            pass 
    443         urlretrieve("http://www.geneontology.org/ontology/gene_ontology_edit.obo",  
     472        urlretrieve("http://www.geneontology.org/ontology/gene_ontology_edit.obo", 
    444473                    os.path.join(tmpDir, "gene_ontology_edit.obo"), 
    445474                    progressCallback and __progressCallbackWrapper(progressCallback)) 
     
    451480    @staticmethod 
    452481    def DownloadOntologyAtRev(rev, filename=None, progressCallback=None): 
    453         import shutil 
    454         import urllib2 
    455482        url = "http://cvsweb.geneontology.org/cgi-bin/cvsweb.cgi/~checkout~/go/ontology/gene_ontology_edit.obo?rev=%s" % rev 
    456483        url += ";content-type=text%2Fplain" 
    457484        if filename is None: 
    458             filename = os.path.join(default_database_path, "gene_ontology_edit@rev%s.obo" % rev) 
     485            filename = os.path.join(default_database_path, 
     486                                    "gene_ontology_edit@rev%s.obo" % rev) 
    459487        r = urllib2.urlopen(url) 
    460          
     488 
    461489        with open(filename + ".part", "wb") as f: 
    462490            shutil.copyfileobj(r, f) 
    463              
     491 
    464492        os.rename(filename + ".part", filename) 
    465          
    466          
     493 
     494 
    467495_re_obj_name_ = re.compile("([a-zA-z0-9-_]+)") 
     496 
    468497 
    469498class AnnotationRecord(object): 
     
    477506    data members for quicker access: geneName, GOId, evidence, aspect and 
    478507    alias(a list of aliases) 
    479      
     508 
    480509    """ 
    481510    __slots__ = annotationFields + ["geneName", "GOId", "evidence", 
    482511                                    "aspect", "alias", "additionalAliases"] 
     512 
    483513    def __init__(self, fullText): 
    484514        """\ 
    485515        :param fulText: A single line from the annotation file. 
    486          
     516 
    487517        """ 
    488518        for slot, val in zip(annotationFields, fullText.split("\t")): 
     
    496526        self.additionalAliases = [] 
    497527        if ":" in self.DB_Object_Name: 
    498             self.additionalAliases = [] #_re_obj_name_.findall(self.DB_Object_Name.split(":")[0]) 
     528            self.additionalAliases = []  # _re_obj_name_.findall(self.DB_Object_Name.split(":")[0]) 
    499529 
    500530    def __getattr__(self, name): 
     
    509539    """ 
    510540    version = 2 
    511     def __init__(self, file=None, ontology=None, genematcher=None, progressCallback=None, rev=None): 
     541 
     542    def __init__(self, file=None, ontology=None, genematcher=None, 
     543                 progressCallback=None, rev=None): 
    512544        """Initialize the annotations from file by calling ParseFile on it. 
    513545        The ontology must be an instance of Ontology class. 
    514546        The optional progressCallback will be called with a single argument 
    515547        to report on the progress. 
    516          
     548 
    517549        """ 
    518550        self.file = file 
     
    545577                if not _CVS_REVISION_RE.match(rev): 
    546578                    raise ValueError("Invalid revision format") 
    547                  
     579 
    548580                if rev.startswith("rev"): 
    549581                    rev = rev[3:] 
    550582                code = self.organism_name_search(file) 
    551583                filename = os.path.join(default_database_path, 
    552                                         "gene_association.%s@rev%s.tar.gz" % (code, rev)) 
    553                  
     584                                        "gene_association.%s@rev%s.tar.gz" % 
     585                                        (code, rev)) 
     586 
    554587                if not os.path.exists(filename): 
    555588                    self.DownloadAnnotationsAtRev(code, rev, filename, 
    556589                                                  progressCallback 
    557590                                                  ) 
    558                      
     591 
    559592                self.ParseFile(filename, progressCallback) 
    560593                self.taxid = to_taxid(code).pop() 
     
    564597                self.taxid = to_taxid(organism_name_search(file)).pop() 
    565598        if not self.genematcher and self.taxid: 
    566             from . import obiGene 
    567             self.genematcher = obiGene.matcher([obiGene.GMGO(self.taxid)] + \ 
    568                                                ([obiGene.GMDicty(), [obiGene.GMGO(self.taxid), 
    569                                                                      obiGene.GMDicty()]] \ 
    570                                                 if self.taxid == "352472"  else [])) 
     599            self.genematcher = obiGene.matcher( 
     600                [obiGene.GMGO(self.taxid)] + 
     601                ([obiGene.GMDicty(), 
     602                  [obiGene.GMGO(self.taxid), obiGene.GMDicty()]] 
     603                 if self.taxid == "352472" else []) 
     604            ) 
    571605        if self.genematcher: 
    572606            self.genematcher.set_targets(self.geneNames) 
    573          
     607 
    574608    @classmethod 
    575609    def organism_name_search(cls, org): 
    576         ids = to_taxid(org)  
     610        ids = to_taxid(org) 
    577611        from . import obiTaxonomy as tax 
    578612        if not ids: 
    579             ids = [org] if org in Taxonomy().common_org_map.keys() + Taxonomy().code_map.keys() else [] 
     613            ids = [org] if org in Taxonomy().common_org_map.keys() + \ 
     614                  Taxonomy().code_map.keys() else [] 
    580615        if not ids: 
    581616            ids = tax.to_taxid(org, mapTo=Taxonomy().keys()) 
     
    588623        codes = set([from_taxid(id) for id in ids]) 
    589624        if len(codes) > 1: 
    590             raise tax.MultipleSpeciesException, ", ".join(["%s: %s" % \ 
    591                             (str(from_taxid(id)), tax.name(id)) for id in ids]) 
     625            raise tax.MultipleSpeciesException( 
     626                ", ".join(["%s: %s" % (str(from_taxid(id)), tax.name(id)) 
     627                           for id in ids])) 
    592628        elif len(codes) == 0: 
    593             raise tax.UnknownSpeciesIdentifier, org 
     629            raise tax.UnknownSpeciesIdentifier(org) 
    594630        return codes.pop() 
    595631 
     
    597633    def organism_version(cls, name): 
    598634        name = organism_name_search(name) 
    599         orngServerFiles.localpath_download("GO", "gene_association.%s.tar.gz" % name) 
     635        orngServerFiles.localpath_download( 
     636            "GO", "gene_association.%s.tar.gz" % name) 
    600637        return ("v%i." % cls.version) + orngServerFiles.info("GO", 
    601638                        "gene_association.%s.tar.gz" % name)["datetime"] 
     
    612649    ontology = property(GetOntology, SetOntology, 
    613650                        doc="Ontology object for annotations") 
    614      
     651 
    615652    @classmethod 
    616653    def Load(cls, org, ontology=None, genematcher=None, progressCallback=None): 
     
    618655        given organism from default_database_path. 
    619656        """ 
    620         from Orange.orng import orngServerFiles 
    621657        code = organism_name_search(org) 
    622          
     658 
    623659        file = "gene_association.%s.tar.gz" % code 
    624660 
     
    633669            orngServerFiles.download("GO", file) 
    634670 
    635         return cls(path, ontology=ontology, genematcher=genematcher, progressCallback=progressCallback) 
    636      
     671        return cls(path, ontology=ontology, genematcher=genematcher, 
     672                   progressCallback=progressCallback) 
     673 
    637674    def ParseFile(self, file, progressCallback=None): 
    638675        """ Parse and load the annotations from file. Report progress 
     
    648685                f = tarfile.open(file).extractfile("gene_association") 
    649686            elif os.path.isfile(file) and file.endswith(".gz"): 
    650                 f = gzip.open(file)  
     687                f = gzip.open(file) 
    651688            elif os.path.isfile(file): 
    652689                f = open(file) 
     
    656693            f = file 
    657694        lines = [line for line in f.read().splitlines() if line.strip()] 
    658         from Orange.orng import orngMisc 
     695 
    659696        milestones = orngMisc.progressBarMilestones(len(lines), 100) 
    660         for i,line in enumerate(lines): 
     697        for i, line in enumerate(lines): 
    661698            if line.startswith("!"): 
    662699                self.header = self.header + line + "\n" 
    663700                continue 
    664              
    665             a=AnnotationRecord(line) 
     701 
     702            a = AnnotationRecord(line) 
    666703            self.AddAnnotation(a) 
    667704#            self.annotations.append(a) 
    668705            if progressCallback and i in milestones: 
    669                 progressCallback(100.0*i/len(lines)) 
     706                progressCallback(100.0 * i / len(lines)) 
    670707 
    671708    def AddAnnotation(self, a): 
     
    677714        if not a.geneName or not a.GOId or a.Qualifier == "NOT": 
    678715            return 
    679          
     716 
    680717        self.geneAnnotations[a.geneName].append(a) 
    681718        self.annotations.append(a) 
    682719        self.termAnnotations[a.GOId].append(a) 
    683720        self.allAnnotations = defaultdict(list) 
    684          
     721 
    685722        self._geneNames = None 
    686723        self._geneNamesDict = None 
     
    706743            self._aliasMapper = {} 
    707744            for ann in self.annotations: 
    708                 self._aliasMapper.update([(alias, ann.geneName) for alias in ann.alias + \ 
    709                                           [ann.geneName, ann.DB_Object_ID]]) 
     745                self._aliasMapper.update([(alias, ann.geneName) 
     746                                          for alias in ann.alias + 
     747                                           [ann.geneName, ann.DB_Object_ID]]) 
    710748        return self._aliasMapper 
    711749 
     
    713751        """ Return a dictionary mapping canonical names (DB_Object_Symbol) 
    714752        to `genes`. 
    715           
     753 
    716754        """ 
    717755        def alias(gene): 
     
    722760                        self.aliasMapper.get(gene, 
    723761                             self.additionalAliases.get(gene, None)) 
    724                          
     762 
    725763        return dict([(alias(gene), gene) for gene in genes if alias(gene)]) 
    726764 
     
    730768        if id not in self.allAnnotations and id not in visited: 
    731769            if id in self.ontology.reverseAliasMapper: 
    732                 annotations = [self.termAnnotations.get(alt_id, []) \ 
    733                                for alt_id in self.ontology.reverseAliasMapper[id]] + \ 
    734                                              [self.termAnnotations[id]] 
     770                annotations = [self.termAnnotations.get(alt_id, []) 
     771                               for alt_id in 
     772                               self.ontology.reverseAliasMapper[id]] + \ 
     773                              [self.termAnnotations[id]] 
    735774            else: 
    736775                ## annotations for this term alone 
    737                 annotations = [self.termAnnotations[id]]  
     776                annotations = [self.termAnnotations[id]] 
    738777            visited.add(id) 
    739778            for typeId, child in self.ontology[id].relatedTo: 
     
    750789        """ Return a set of all annotations (instances if `AnnotationRectord`) 
    751790        for GO term `id` and all it's subterms. 
    752          
     791 
    753792        :param id: GO term id 
    754793        :type id: str 
    755          
     794 
    756795        """ 
    757796        visited = set() 
    758797        id = self.ontology.aliasMapper.get(id, id) 
    759         if id not in self.allAnnotations or type(self.allAnnotations[id]) == list: 
     798        if id not in self.allAnnotations or \ 
     799                type(self.allAnnotations[id]) == list: 
    760800            annot_set = set() 
    761801            for annots in self._CollectAnnotations(id, set()): 
     
    764804        return self.allAnnotations[id] 
    765805 
    766     def GetAllGenes(self, id, evidenceCodes = None): 
     806    def GetAllGenes(self, id, evidenceCodes=None): 
    767807        """ Return a list of genes annotated by specified `evidenceCodes` 
    768808        to GO term 'id' and all it's subterms." 
    769          
     809 
    770810        :param id: GO term id 
    771811        :type id: str 
    772          
     812 
    773813        :param evidneceCodes: List of evidence codes to consider when 
    774814                              matching annotations to terms. 
     
    777817        evidenceCodes = set(evidenceCodes or evidenceDict.keys()) 
    778818        annotations = self.GetAllAnnotations(id) 
    779         return list(set([ann.geneName for ann in annotations if ann.Evidence_Code in evidenceCodes])) 
    780  
    781     def GetEnrichedTerms(self, genes, reference=None, evidenceCodes=None,  
     819        return list(set([ann.geneName for ann in annotations 
     820                         if ann.Evidence_Code in evidenceCodes])) 
     821 
     822    def GetEnrichedTerms(self, genes, reference=None, evidenceCodes=None, 
    782823                         slimsOnly=False, aspect=None, prob=obiProb.Binomial(), 
    783824                         useFDR=True, progressCallback=None): 
     
    785826        (list_of_genes, p_value, reference_count) for items and term 
    786827        ids as keys. P-Values are FDR adjusted if useFDR is True (default). 
    787          
     828 
    788829        :param genes: List of genes 
    789830        :param reference: list of genes (if None all genes included in the 
     
    804845        if aspect == None: 
    805846            aspects_set = set(["P", "C", "F"]) 
     847        elif isinstance(aspect, basestring): 
     848            aspects_set = set([aspect]) 
    806849        else: 
    807             aspects_set = set([aspect]) if isinstance(aspect, basestring) else aspect 
     850            aspects_set = aspect 
    808851 
    809852        evidenceCodes = set(evidenceCodes or evidenceDict.keys()) 
    810         annotations = [ann for gene in genes for ann in self.geneAnnotations[gene] \ 
    811                        if ann.Evidence_Code in evidenceCodes and ann.Aspect in aspects_set] 
    812         refAnnotations = set([ann for gene in reference for ann in self.geneAnnotations[gene] \ 
    813                               if ann.Evidence_Code in evidenceCodes and ann.Aspect in aspects_set]) 
     853        annotations = [ann 
     854                       for gene in genes for ann in self.geneAnnotations[gene] 
     855                       if ann.Evidence_Code in evidenceCodes and 
     856                       ann.Aspect in aspects_set] 
     857 
     858        refAnnotations = set( 
     859            [ann 
     860             for gene in reference for ann in self.geneAnnotations[gene] 
     861             if ann.Evidence_Code in evidenceCodes and 
     862             ann.Aspect in aspects_set] 
     863        ) 
     864 
    814865        annotationsDict = defaultdict(set) 
    815866        for ann in annotations: 
    816867            annotationsDict[ann.GO_ID].add(ann) 
    817              
     868 
    818869        if slimsOnly and not self.ontology.slimsSubset: 
    819             import warnings 
    820             warnings.warn("Unspecified slims subset in the ontology! Using 'goslim_generic' subset", UserWarning) 
     870            warnings.warn("Unspecified slims subset in the ontology! " 
     871                          "Using 'goslim_generic' subset", UserWarning) 
    821872            self.ontology.SetSlimsSubset("goslim_generic") 
    822              
     873 
    823874        terms = self.ontology.ExtractSuperGraph(annotationsDict.keys()) 
    824875        res = {} 
    825         from Orange.orng import orngMisc 
     876 
    826877        milestones = orngMisc.progressBarMilestones(len(terms), 100) 
    827878        for i, term in enumerate(terms): 
     
    847898                progressCallback(100.0 * i / len(terms)) 
    848899        if useFDR: 
    849             res = sorted(res.items(), key = lambda (_1, (_2, p, _3)): p) 
    850             res = dict([(id, (genes, p, ref)) \ 
    851                         for (id, (genes, _, ref)), p in zip(res, obiProb.FDR([p for _, (_, p, _) in res]))]) 
     900            res = sorted(res.items(), key=lambda (_1, (_2, p, _3)): p) 
     901            res = dict([(id, (genes, p, ref)) 
     902                        for (id, (genes, _, ref)), p in 
     903                        zip(res, obiProb.FDR([p for _, (_, p, _) in res]))]) 
    852904        return res 
    853905 
    854     def GetAnnotatedTerms(self, genes, directAnnotationOnly=False, evidenceCodes=None, progressCallback=None): 
     906    def GetAnnotatedTerms(self, genes, directAnnotationOnly=False, 
     907                          evidenceCodes=None, progressCallback=None): 
    855908        """ Return all terms that are annotated by genes with evidenceCodes. 
    856909        """ 
     
    859912        genes = set(revGenesDict.keys()) 
    860913        evidenceCodes = set(evidenceCodes or evidenceDict.keys()) 
    861         annotations = [ann for gene in genes for ann in self.geneAnnotations[gene] \ 
     914        annotations = [ann for gene in genes for ann in self.geneAnnotations[gene] 
    862915                       if ann.Evidence_Code in evidenceCodes] 
    863916        dd = defaultdict(set) 
     
    869922                termAnnots = self.GetAllAnnotations(term).intersection(annotations) 
    870923##                termAnnots.intersection_update(annotations) 
    871                 dd[term].update([revGenesDict.get(ann.geneName, ann.geneName) for ann in termAnnots]) 
     924                dd[term].update([revGenesDict.get(ann.geneName, ann.geneName) 
     925                                 for ann in termAnnots]) 
    872926        return dict(dd) 
    873927 
    874     def DrawEnrichmentGraph(self, terms, clusterSize, refSize=None, file="graph.png", width=None, height=None, precison=3): 
     928    def DrawEnrichmentGraph(self, terms, clusterSize, refSize=None, 
     929                            file="graph.png", width=None, height=None, 
     930                            precison=3): 
    875931        refSize = len(self.geneNames) if refSize == None else refSize 
    876         sortedterms = sorted(terms.items(), key=lambda term:term[1][1]) 
    877         fdr = dict(zip([t[0] for t in sortedterms], obiProb.FDR([t[1][1] for t in sortedterms]))) 
    878         termsList = [(term, (float(len(terms[term][0]))/clusterSize) / (float(terms[term][2])/refSize), 
    879                       len(terms[term][0]), terms[term][2], terms[term][1], 
    880                       fdr[term], terms[term][0]) for term in terms] 
    881                            
    882         drawEnrichmentGraph(termsList, file, width, height, ontology=self.ontology, precison=precison) 
     932        sortedterms = sorted(terms.items(), key=lambda term: term[1][1]) 
     933        fdr = dict(zip([t[0] for t in sortedterms], 
     934                       obiProb.FDR([t[1][1] for t in sortedterms]))) 
     935        termsList = [(term, 
     936                      ((float(len(terms[term][0])) / clusterSize) / 
     937                       (float(terms[term][2]) / refSize)), 
     938                      len(terms[term][0]), 
     939                      terms[term][2], 
     940                      terms[term][1], 
     941                      fdr[term], 
     942                      terms[term][0]) 
     943                     for term in terms] 
     944 
     945        drawEnrichmentGraph(termsList, file, width, height, 
     946                            ontology=self.ontology, precison=precison) 
    883947 
    884948    def __add__(self, iterable): 
    885949        """ Return a new Annotations object with combined annotations 
    886950        """ 
    887         return Annotations([a for a in self] + [a for a in iterable], ontology=self.ontology) 
     951        return Annotations([a for a in self] + [a for a in iterable], 
     952                           ontology=self.ontology) 
    888953 
    889954    def __iadd__(self, iterable): 
     
    895960    def __contains__(self, item): 
    896961        return item in self.annotations 
    897              
     962 
    898963    def __iter__(self): 
    899964        """ Iterate over all AnnotationRecord objects in annotations 
     
    931996 
    932997    def RemapGenes(self, map): 
    933         """  
    934         """ 
    935         from copy import copy 
     998        """ 
     999        """ 
    9361000        for gene in map: 
    9371001            annotations = self.geneAnnotations[gene] 
    9381002            for ann in annotations: 
    9391003                for name in map[gene]: 
    940                     ann1 = copy(ann) 
     1004                    ann1 = copy.copy(ann) 
    9411005                    ann1.geneName = name 
    9421006                    self.add(ann1) 
     
    9471011            pass 
    9481012        self.genematcher.set_targets(self.geneNames) 
    949      
     1013 
    9501014    @staticmethod 
    9511015    def DownloadAnnotations(org, file, progressCallback=None): 
     
    9571021            pass 
    9581022        fileName = "gene_association." + org + ".gz" 
    959         urlretrieve("http://www.geneontology.org/gene-associations/" + fileName, 
     1023        urlretrieve(("http://www.geneontology.org/gene-associations/" + 
     1024                     fileName), 
    9601025                    os.path.join(tmpDir, fileName), 
    961                     progressCallback and __progressCallbackWraper(progressCallback)) 
     1026                    progressCallback and __progressCallbackWrapper(progressCallback)) 
    9621027        gzFile = GzipFile(os.path.join(tmpDir, fileName), "r") 
    9631028        file = open(os.path.join(tmpDir, "gene_association." + org), "w") 
     
    9651030        file.flush() 
    9661031        file.close() 
    967 ##        tFile = tarfile.open(os.path.join(tmpDir, "gene_association." + org + ".tar.gz"), "w:gz") 
    968         tFile.add(os.path.join(tmpDir, "gene_association." + org), "gene_association") 
     1032 
     1033        tFile.add(os.path.join(tmpDir, "gene_association." + org), 
     1034                  "gene_association") 
    9691035        annotation = Annotations(os.path.join(tmpDir, "gene_association." + org), 
    9701036                    genematcher=obiGene.GMDirect(), progressCallback=progressCallback) 
     
    9741040        os.remove(os.path.join(tmpDir, "gene_association." + org)) 
    9751041        os.remove(os.path.join(tmpDir, "gene_names.pickle")) 
    976          
     1042 
    9771043    @staticmethod 
    978     def DownloadAnnotationsAtRev(org, rev, filename=None, progressCallback=None): 
    979         import urllib2 
    980         import shutil 
     1044    def DownloadAnnotationsAtRev(org, rev, filename=None, 
     1045                                 progressCallback=None): 
    9811046        if filename is None: 
    9821047            filename = os.path.join(default_database_path, 
    983                                     "gene_association.%s@rev%s.tar.gz" % (code, rev)) 
    984         url = "http://cvsweb.geneontology.org/cgi-bin/cvsweb.cgi/~checkout~/go/gene-associations/gene_association.%s.gz?rev=%s" % (org, rev) 
     1048                                    "gene_association.%s@rev%s.tar.gz" % 
     1049                                    (code, rev)) 
     1050        url = ("http://cvsweb.geneontology.org/cgi-bin/cvsweb.cgi/~checkout~/go/gene-associations/gene_association.%s.gz?rev=%s" % 
     1051               (org, rev)) 
    9851052        url += ";content-type=application%2Fx-gzip" 
    9861053        r = urllib2.urlopen(url) 
    987          
     1054 
    9881055        with open(filename + ".part", "wb") as f: 
    9891056            shutil.copyfileobj(r, f) 
    990          
     1057 
    9911058        os.rename(filename + ".part", filename) 
    9921059 
    9931060from .obiTaxonomy import pickled_cache 
    9941061 
    995 @pickled_cache(None, [("GO", "taxonomy.pickle"), ("Taxonomy", "ncbi_taxonomy.tar.gz")]) 
     1062 
     1063@pickled_cache(None, [("GO", "taxonomy.pickle"), 
     1064                      ("Taxonomy", "ncbi_taxonomy.tar.gz")]) 
    9961065def organism_name_search(name): 
    9971066    return Annotations.organism_name_search(name) 
     1067 
    9981068 
    9991069def filterByPValue(terms, maxPValue=0.1): 
    10001070    """ Filters the terms by the p-value. Asumes terms is a dict with 
    10011071    the same structure as returned from GetEnrichedTerms. 
    1002      
     1072 
    10031073    """ 
    1004     return dict(filter(lambda (k,e): e[1]<=maxPValue, terms.items())) 
     1074    return dict(filter(lambda (k, e): e[1] <= maxPValue, terms.items())) 
     1075 
    10051076 
    10061077def filterByFrequency(terms, minF=2): 
    10071078    """ Filters the terms by the cluster frequency. Asumes terms is 
    10081079    a dict with the same structure as returned from GetEnrichedTerms. 
    1009      
     1080 
    10101081    """ 
    1011     return dict(filter(lambda (k,e): len(e[0])>=minF, terms.items())) 
     1082    return dict(filter(lambda (k, e): len(e[0]) >= minF, terms.items())) 
     1083 
    10121084 
    10131085def filterByRefFrequency(terms, minF=4): 
    10141086    """ Filters the terms by the reference frequency. Asumes terms is 
    10151087    a dict with the same structure as returned from GetEnrichedTerms. 
    1016      
     1088 
    10171089    """ 
    1018     return dict(filter(lambda (k,e): e[2]>=minF, terms.items())) 
    1019  
    1020 ##def drawEnrichmentGraph(termsList, clusterSize, refSize, filename="graph.png", width=None, height=None): 
    1021 ##    if type(termsList) == dict: 
    1022 ##        termsList = [(term, (float(len(termsList[term][0]))/clusterSize) / (float(termsList[term][2])/refSize), 
    1023 ##                      len(termsList[term][0]), termsList[term][2], termsList[term][1], 1.0, termsList[term][0]) for term in termsList] 
    1024 ##                      
    1025 ##                      
    1026 ##                              
    1027 ##    drawEnrichmentGraph_tostreamMk2(termsList, open(filename, "wb"), width, height) 
     1090    return dict(filter(lambda (k, e): e[2] >= minF, terms.items())) 
     1091 
    10281092 
    10291093def drawEnrichmentGraph_tostream(GOTerms, clusterSize, refSize, fh, width=None, height=None): 
    10301094    def getParents(term): 
    10311095        parents = extractGODAG([term]) 
    1032         parents = filter(lambda t: t.id in GOTerms and t.id!=term, parents) 
     1096        parents = filter(lambda t: t.id in GOTerms and t.id != term, parents) 
    10331097        c = [] 
    10341098        map(c.extend, [getParents(t.id) for t in parents]) 
     
    10361100        return parents 
    10371101    parents = dict([(term, getParents(term)) for term in GOTerms]) 
    1038     #print "Parentes", parents 
     1102    # print "Parentes", parents 
     1103 
    10391104    def getChildren(term): 
    10401105        return filter(lambda t: term in [p.id for p in parents[t]], GOTerms.keys()) 
    10411106    topLevelTerms = filter(lambda t: not parents[t], parents.keys()) 
    1042     #print "Top level terms", topLevelTerms 
    1043     termsList=[] 
     1107    # print "Top level terms", topLevelTerms 
     1108    termsList = [] 
     1109 
    10441110    def collect(term, parent): 
    10451111        termsList.append( 
    1046             ((float(len(GOTerms[term][0]))/clusterSize) / (float(GOTerms[term][2])/refSize), 
     1112            ((float(len(GOTerms[term][0])) / clusterSize) / (float(GOTerms[term][2]) / refSize), 
    10471113            len(GOTerms[term][0]), 
    10481114            GOTerms[term][2], 
     
    10541120            ) 
    10551121##        print float(len(GOTerms[term][0])), float(GOTerms[term][2]), clusterSize, refSize 
    1056         parent = len(termsList)-1 
     1122        parent = len(termsList) - 1 
    10571123        for c in getChildren(term): 
    10581124            collect(c, parent) 
    1059                           
     1125 
    10601126    for topTerm in topLevelTerms: 
    10611127        collect(topTerm, None) 
     
    10631129    drawEnrichmentGraphPIL_tostream(termsList, fh, width, height) 
    10641130 
    1065 def drawEnrichmentGraph(enriched, file="graph.png", width=None, height=None, header=None, ontology = None, precison=3): 
     1131 
     1132def drawEnrichmentGraph(enriched, file="graph.png", width=None, height=None, header=None, ontology=None, precison=3): 
    10661133    file = open(file, "wb") if type(file) == str else file 
    1067     drawEnrichmentGraph_tostreamMk2(enriched, file,  width, height, header, ontology, precison) 
    1068      
    1069 def drawEnrichmentGraph_tostreamMk2(enriched, fh, width, height, header=None, ontology = None, precison=4): 
     1134    drawEnrichmentGraph_tostreamMk2(enriched, file, width, height, header, ontology, precison) 
     1135 
     1136 
     1137def drawEnrichmentGraph_tostreamMk2(enriched, fh, width, height, header=None, ontology=None, precison=4): 
    10701138    ontology = ontology if ontology else Ontology() 
    1071     header = header if header else ["List", "Total", "p-value", "FDR", "Names", "Genes"] 
     1139    header = header if header else ["List", "Total", "p-value", "FDR", 
     1140                                    "Names", "Genes"] 
    10721141    GOTerms = dict([(t[0], t) for t in enriched if t[0] in ontology]) 
     1142 
    10731143    def getParents(term): 
    10741144        parents = ontology.ExtractSuperGraph([term]) 
    10751145        parents = [id for id in parents if id in GOTerms and id != term] 
    1076         c = reduce(set.union, [set(ontology.ExtractSuperGraph([id])) - set([id]) for id in parents], set()) 
     1146        c = reduce(set.union, [set(ontology.ExtractSuperGraph([id])) - 
     1147                               set([id]) for id in parents], set()) 
    10771148        parents = [t for t in parents if t not in c] 
    10781149        return parents 
    10791150    parents = dict([(term, getParents(term)) for term in GOTerms]) 
    1080     #print "Parentes", parents 
     1151    # print "Parentes", parents 
     1152 
    10811153    def getChildren(term): 
    10821154        return [id for id in GOTerms if term in parents[id]] 
    10831155    topLevelTerms = [id for id in parents if not parents[id]] 
    1084     #print "Top level terms", topLevelTerms 
    1085     termsList=[] 
     1156    # print "Top level terms", topLevelTerms 
     1157    termsList = [] 
    10861158    fmt = "%" + ".%if" % precison 
     1159 
    10871160    def collect(term, parent): 
    10881161##        termsList.append( 
     
    11021175                          ", ".join(GOTerms[term][6])) + (parent,)) 
    11031176##        print float(len(GOTerms[term][0])), float(GOTerms[term][2]), clusterSize, refSize 
    1104         parent = len(termsList)-1 
     1177        parent = len(termsList) - 1 
    11051178        for c in getChildren(term): 
    11061179            collect(c, parent) 
    1107                           
     1180 
    11081181    for topTerm in topLevelTerms: 
    11091182        collect(topTerm, None) 
     
    11171190 
    11181191    drawEnrichmentGraphPIL_tostream(termsList, header, fh, width, height) 
    1119 ##    drawEnrichmentGraphPylab_tostream(termsList, header, fh, width, height) 
    1120      
     1192 
     1193 
    11211194def drawEnrichmentGraphPIL_tostream(termsList, headers, fh, width=None, height=None): 
    11221195    from PIL import Image, ImageDraw, ImageFont 
     
    11241197    textColor = (0, 0, 0) 
    11251198    graphColor = (0, 0, 255) 
    1126     fontSize = height==None and 12 or (height-60)/len(termsList) 
     1199    fontSize = height == None and 12 or (height - 60) / len(termsList) 
    11271200    font = ImageFont.load_default() 
    11281201    try: 
     
    11321205    getMaxTextHeightHint = lambda l: max([font.getsize(t)[1] for t in l]) 
    11331206    getMaxTextWidthHint = lambda l: max([font.getsize(t)[0] for t in l]) 
    1134     maxFoldWidth = width!=None and min(150, width/6) or 150 
     1207    maxFoldWidth = width != None and min(150, width / 6) or 150 
    11351208    maxFoldEnrichment = max([t[0] for t in termsList]) 
    1136     foldNormalizationFactor = float(maxFoldWidth)/maxFoldEnrichment 
    1137     foldWidths = [int(foldNormalizationFactor*term[0]) for term in termsList] 
     1209    foldNormalizationFactor = float(maxFoldWidth) / maxFoldEnrichment 
     1210    foldWidths = [int(foldNormalizationFactor * term[0]) for term in termsList] 
    11381211    treeStep = 10 
    11391212    treeWidth = {} 
    11401213    for i, term in enumerate(termsList): 
    1141         treeWidth[i] = (term[-1]==None and 1 or treeWidth[term[-1]]+1) 
    1142     treeStep = width!=None and min(treeStep, width/(6*max(treeWidth.values())) or 2) or treeStep 
    1143     treeWidth = [w*treeStep + foldWidths[i] for i, w in treeWidth.items()] 
     1214        treeWidth[i] = (term[-1] == None and 1 or treeWidth[term[-1]] + 1) 
     1215    treeStep = width != None and min(treeStep, width / (6 * max(treeWidth.values())) or 2) or treeStep 
     1216    treeWidth = [w * treeStep + foldWidths[i] for i, w in treeWidth.items()] 
    11441217    treeWidth = max(treeWidth) - maxFoldWidth 
    11451218    verticalMargin = 10 
     
    11481221##    treeWidth = 100 
    11491222    firstColumnStart = verticalMargin + maxFoldWidth + treeWidth + 10 
    1150     secondColumnStart = firstColumnStart + getMaxTextWidthHint([str(t[1]) for t in termsList]+[headers[0]]) + 2 
    1151     thirdColumnStart = secondColumnStart + getMaxTextWidthHint([str(t[2]) for t in termsList]+[headers[1]]) + 2 
    1152     fourthColumnStart = thirdColumnStart + getMaxTextWidthHint([str(t[3]) for t in termsList]+[headers[2]]) + 2 
    1153     fifthColumnStart = fourthColumnStart + getMaxTextWidthHint([str(t[4]) for t in termsList]+[headers[3]]) + 4 
     1223    secondColumnStart = firstColumnStart + getMaxTextWidthHint([str(t[1]) for t in termsList] + [headers[0]]) + 2 
     1224    thirdColumnStart = secondColumnStart + getMaxTextWidthHint([str(t[2]) for t in termsList] + [headers[1]]) + 2 
     1225    fourthColumnStart = thirdColumnStart + getMaxTextWidthHint([str(t[3]) for t in termsList] + [headers[2]]) + 2 
     1226    fifthColumnStart = fourthColumnStart + getMaxTextWidthHint([str(t[4]) for t in termsList] + [headers[3]]) + 4 
    11541227##    maxAnnotationTextWidth = width==None and getMaxTextWidthHint([str(t[4]) for t in termsList]+["Annotation"]) or (width - fourthColumnStart - verticalMargin) * 2 / 3 
    1155     maxAnnotationTextWidth = width==None and getMaxTextWidthHint([str(t[5]) for t in termsList]+[headers[4]]) or max((width - fifthColumnStart - verticalMargin) * 2 / 3, getMaxTextWidthHint([t[5] for t in termsList]+[headers[4]])) 
    1156     sixthColumnStart  = fifthColumnStart + maxAnnotationTextWidth + 4 
    1157     maxGenesTextWidth = width==None and getMaxTextWidthHint([str(t[6]) for t in termsList]+[headers[5]]) or (width - fifthColumnStart - verticalMargin) / 3 
    1158      
    1159     legendHeight = font.getsize("1234567890")[1]*2 
     1228    maxAnnotationTextWidth = width == None and getMaxTextWidthHint([str(t[5]) for t in termsList] + [headers[4]]) or max((width - fifthColumnStart - verticalMargin) * 2 / 3, getMaxTextWidthHint([t[5] for t in termsList] + [headers[4]])) 
     1229    sixthColumnStart = fifthColumnStart + maxAnnotationTextWidth + 4 
     1230    maxGenesTextWidth = width == None and getMaxTextWidthHint([str(t[6]) for t in termsList] + [headers[5]]) or (width - fifthColumnStart - verticalMargin) / 3 
     1231 
     1232    legendHeight = font.getsize("1234567890")[1] * 2 
    11601233    termHeight = font.getsize("A")[1] 
    11611234##    print fourthColumnStart, maxAnnotationTextWidth, verticalMargin 
    11621235    width = sixthColumnStart + maxGenesTextWidth + verticalMargin 
    1163     height = len(termsList)*termHeight+2*(legendHeight+horizontalMargin) 
     1236    height = len(termsList) * termHeight + 2 * (legendHeight + horizontalMargin) 
    11641237 
    11651238    image = Image.new("RGB", (width, height), backgroundColor) 
     
    11671240 
    11681241    def truncText(text, maxWidth, append=""): 
    1169         #print getMaxTextWidthHint([text]), maxAnnotationTextWidth 
    1170         if getMaxTextWidthHint([text])>maxWidth: 
    1171             while getMaxTextWidthHint([text+"..."+append])>maxWidth and text: 
     1242        # print getMaxTextWidthHint([text]), maxAnnotationTextWidth 
     1243        if getMaxTextWidthHint([text]) > maxWidth: 
     1244            while getMaxTextWidthHint([text + "..." + append]) > maxWidth and text: 
    11721245                text = text[:-1] 
    11731246            if text: 
    1174                 text = text+"..."+append 
     1247                text = text + "..." + append 
    11751248            else: 
    11761249                text = append 
     
    11791252    connectAtX = {} 
    11801253    for i, term in enumerate(termsList): 
    1181         draw.line([(verticalMargin, currentY+termHeight/2), (verticalMargin + foldWidths[i], currentY+termHeight/2)], width=termHeight-2, fill=graphColor) 
     1254        draw.line([(verticalMargin, currentY + termHeight / 2), (verticalMargin + foldWidths[i], currentY + termHeight / 2)], width=termHeight - 2, fill=graphColor) 
    11821255        draw.text((firstColumnStart, currentY), str(term[1]), font=font, fill=textColor) 
    11831256        draw.text((secondColumnStart, currentY), str(term[2]), font=font, fill=textColor) 
     
    11851258        draw.text((fourthColumnStart, currentY), str(term[4]), font=font, fill=textColor) 
    11861259##        annotText = width!=None and truncText(str(term[5]), maxAnnotationTextWidth, str(term[5])) or str(term[4]) 
    1187         annotText = width!=None and truncText(str(term[5]), maxAnnotationTextWidth) 
     1260        annotText = width != None and truncText(str(term[5]), maxAnnotationTextWidth) 
    11881261        draw.text((fifthColumnStart, currentY), annotText, font=font, fill=textColor) 
    1189         genesText = width!=None and truncText(str(term[6]), maxGenesTextWidth) or str(term[6]) 
     1262        genesText = width != None and truncText(str(term[6]), maxGenesTextWidth) or str(term[6]) 
    11901263        draw.text((sixthColumnStart, currentY), genesText, font=font, fill=textColor) 
    1191         lineEnd = term[-1]==None and firstColumnStart-10 or connectAtX[term[-1]] 
    1192         draw.line([(verticalMargin+foldWidths[i]+1, currentY+termHeight/2), (lineEnd, currentY+termHeight/2)], width=1, fill=textColor) 
    1193         if term[-1]!=None: 
    1194             draw.line([(lineEnd, currentY+termHeight/2), (lineEnd, currentY+termHeight/2 - termHeight*(i-term[-1]))], width=1, fill=textColor) 
     1264        lineEnd = term[-1] == None and firstColumnStart - 10 or connectAtX[term[-1]] 
     1265        draw.line([(verticalMargin + foldWidths[i] + 1, currentY + termHeight / 2), (lineEnd, currentY + termHeight / 2)], width=1, fill=textColor) 
     1266        if term[-1] != None: 
     1267            draw.line([(lineEnd, currentY + termHeight / 2), (lineEnd, currentY + termHeight / 2 - termHeight * (i - term[-1]))], width=1, fill=textColor) 
    11951268        connectAtX[i] = lineEnd - treeStep 
    1196         currentY+=termHeight 
     1269        currentY += termHeight 
    11971270 
    11981271    currentY = horizontalMargin 
     
    12051278 
    12061279    horizontalMargin = 0 
    1207     #draw.line([(verticalMargin, height - horizontalMargin - legendHeight), (verticalMargin + maxFoldWidth, height - horizontalMargin - legendHeight)], width=1, fill=textColor) 
     1280    # draw.line([(verticalMargin, height - horizontalMargin - legendHeight), (verticalMargin + maxFoldWidth, height - horizontalMargin - legendHeight)], width=1, fill=textColor) 
    12081281    draw.line([(verticalMargin, horizontalMargin + legendHeight), (verticalMargin + maxFoldWidth, horizontalMargin + legendHeight)], width=1, fill=textColor) 
    1209     maxLabelWidth = getMaxTextWidthHint([" "+str(i) for i in range(int(maxFoldEnrichment+1))]) 
    1210     numOfLegendLabels = max(int(maxFoldWidth/maxLabelWidth), 2) 
    1211     for i in range(numOfLegendLabels+1): 
    1212         #draw.line([(verticalMargin + i*maxFoldWidth/10, height - horizontalMargin - legendHeight/2), (verticalMargin + i*maxFoldWidth/10, height - horizontalMargin - legendHeight)], width=1, fill=textColor) 
    1213         #draw.text((verticalMargin + i*maxFoldWidth/10 - font.getsize(str(i))[0]/2, height - horizontalMargin - legendHeight/2), str(i), font=font, fill=textColor) 
    1214  
    1215         label = str(int(i*maxFoldEnrichment/numOfLegendLabels)) 
    1216         draw.line([(verticalMargin + i*maxFoldWidth/numOfLegendLabels, horizontalMargin + legendHeight/2), (verticalMargin + i*maxFoldWidth/numOfLegendLabels, horizontalMargin + legendHeight)], width=1, fill=textColor) 
    1217         draw.text((verticalMargin + i*maxFoldWidth/numOfLegendLabels - font.getsize(label)[0]/2, horizontalMargin), label, font=font, fill=textColor) 
    1218          
     1282    maxLabelWidth = getMaxTextWidthHint([" " + str(i) for i in range(int(maxFoldEnrichment + 1))]) 
     1283    numOfLegendLabels = max(int(maxFoldWidth / maxLabelWidth), 2) 
     1284    for i in range(numOfLegendLabels + 1): 
     1285        # draw.line([(verticalMargin + i*maxFoldWidth/10, height - horizontalMargin - legendHeight/2), (verticalMargin + i*maxFoldWidth/10, height - horizontalMargin - legendHeight)], width=1, fill=textColor) 
     1286        # draw.text((verticalMargin + i*maxFoldWidth/10 - font.getsize(str(i))[0]/2, height - horizontalMargin - legendHeight/2), str(i), font=font, fill=textColor) 
     1287 
     1288        label = str(int(i * maxFoldEnrichment / numOfLegendLabels)) 
     1289        draw.line([(verticalMargin + i * maxFoldWidth / numOfLegendLabels, horizontalMargin + legendHeight / 2), (verticalMargin + i * maxFoldWidth / numOfLegendLabels, horizontalMargin + legendHeight)], width=1, fill=textColor) 
     1290        draw.text((verticalMargin + i * maxFoldWidth / numOfLegendLabels - font.getsize(label)[0] / 2, horizontalMargin), label, font=font, fill=textColor) 
     1291 
    12191292    image.save(fh) 
     1293 
    12201294 
    12211295def drawEnrichmentGraphPylab_tostream(termsList, headers, fh, width=None, height=None, show=True): 
    12221296    from matplotlib import pyplot as plt 
    12231297    from matplotlib.patches import Rectangle 
    1224      
    1225     maxFoldWidth = width!=None and min(150, width/6) or 150 
     1298 
     1299    maxFoldWidth = width != None and min(150, width / 6) or 150 
    12261300    maxFoldEnrichment = max([t[0] for t in termsList]) 
    1227     foldNormalizationFactor = float(maxFoldWidth)/maxFoldEnrichment 
     1301    foldNormalizationFactor = float(maxFoldWidth) / maxFoldEnrichment 
    12281302##    foldWidths = [int(foldNormalizationFactor*term[0]) for term in termsList] 
    12291303    foldWidths = [term[0] for term in termsList] 
    1230     treeStep = maxFoldEnrichment*0.05 
     1304    treeStep = maxFoldEnrichment * 0.05 
    12311305    treeWidth = {} 
    12321306 
    12331307    for i, term in enumerate(termsList): 
    1234         treeWidth[i] = (term[-1]==None and treeStep or treeWidth[term[-1]] + treeStep) 
     1308        treeWidth[i] = (term[-1] == None and treeStep or treeWidth[term[-1]] + treeStep) 
    12351309    maxTreeWidth = max(treeWidth) 
    12361310 
     
    12451319        connectAt[i] = connectAt.get(parent, maxFoldEnrichment + maxTreeWidth) - treeStep 
    12461320        if parent != None: 
    1247             plt.plot([connectAt.get(parent)]*2, [len(termsList) - i, len(termsList) - parent], color="black") 
     1321            plt.plot([connectAt.get(parent)] * 2, [len(termsList) - i, len(termsList) - parent], color="black") 
    12481322        cellText.append((str(n), str(m), p_val, fdr_val, name, genes)) 
    12491323 
     
    12571331        for i, line in enumerate(cellText): 
    12581332            for j, text in enumerate(line): 
    1259                 table.add_cell(i, j,width=len(text), height=1, text=text, loc="left", edgecolor="w", facecolor="w") 
     1333                table.add_cell(i, j, width=len(text), height=1, text=text, loc="left", edgecolor="w", facecolor="w") 
    12601334 
    12611335        table.set_figure(plt.gcf()) 
     
    12661340##    table = plt.table(cellText=cellText, colLabels=headers, loc="right") 
    12671341##    table.set_transform(plt.gca().transData) 
    1268 ##     
     1342## 
    12691343##    table.set_xy(20,20) 
    12701344    plt.show() 
    1271      
     1345 
     1346 
    12721347class Taxonomy(object): 
    1273     """Maps NCBI taxonomy ids to coresponding GO organism codes 
     1348    """Maps NCBI taxonomy ids to corresponding GO organism codes 
    12741349    """ 
    1275     common_org_map = {"297284":"9913", "30523":"9913", # Bos taurus 
    1276                       "5782":"352472", "44689":"352472", "366501":"352472", # Dictyostelium discoideum 
    1277                       "83333": "562", # Escherichia coli 
    1278                       "52545":"4530", "4532":"4530", "65489":"4530", "4533":"4530", "77588":"4530", "29689":"4530", 
    1279                       "4538":"4530", "40148":"4530", "29690":"4530", "110450":"4530", "4534":"4530", "83309":"4530", 
    1280                       "4528":"4530", "127571":"4530", "40149":"4530", "83307":"4530", "63629":"4530", "4536": "4530", 
    1281                       "4535":"4530", "4537":"4530", "65491":"4530", "83308":"4530", "4529":"4530", "4530":"4530", 
    1282                       "39946":"4530", "39947":"4530", "110451":"4530", "364100":"4530", "364099":"4530", "4539":"4530", 
     1350    common_org_map = {"297284": "9913", "30523": "9913", # Bos taurus 
     1351                      "5782": "352472", "44689": "352472", "366501": "352472", # Dictyostelium discoideum 
     1352                      "83333": "562",  # Escherichia coli 
     1353                      "52545": "4530", "4532": "4530", "65489": "4530", "4533": "4530", "77588": "4530", "29689": "4530", 
     1354                      "4538": "4530", "40148": "4530", "29690": "4530", "110450": "4530", "4534": "4530", "83309": "4530", 
     1355                      "4528": "4530", "127571": "4530", "40149": "4530", "83307": "4530", "63629": "4530", "4536": "4530", 
     1356                      "4535": "4530", "4537": "4530", "65491": "4530", "83308": "4530", "4529": "4530", "4530": "4530", 
     1357                      "39946": "4530", "39947": "4530", "110451": "4530", "364100": "4530", "364099": "4530", "4539": "4530", 
    12831358                      } 
    1284     code_map = {"3702":"tair",  # Arabidopsis thaliana 
    1285                 "9913":"goa_cow", # Bos taurus 
    1286                 "6239":"wb", # Caenorhabditis elegans 
    1287                 "3055":None, # Chlamydomonas reinhardtii 
    1288                 "7955":"zfin", # Danio rerio (zebrafish) 
    1289                 "352472":"dictyBase", # Dictyostelium discoideum 
    1290                 "7227": "fb", # Drosophila melanogaster 
    1291                 "562": "ecocyc", # Escherichia coli 
    1292                 "11103": None, # Hepatitis C virus 
     1359    code_map = {"3702": "tair",  # Arabidopsis thaliana 
     1360                "9913": "goa_cow", # Bos taurus 
     1361                "6239": "wb", # Caenorhabditis elegans 
     1362                "3055": None, # Chlamydomonas reinhardtii 
     1363                "7955": "zfin", # Danio rerio (zebrafish) 
     1364                "352472": "dictyBase", # Dictyostelium discoideum 
     1365                "7227": "fb",  # Drosophila melanogaster 
     1366                "562": "ecocyc",  # Escherichia coli 
     1367                "11103": None,  # Hepatitis C virus 
    12931368                "9606": "goa_human",  # Homo sapiens 
    1294                 "10090": "mgi", # Mus musculus 
     1369                "10090": "mgi",  # Mus musculus 
    12951370                "2104": None,  # Mycoplasma pneumoniae 
    12961371                "4530": "gramene_oryza",  # Oryza sativa 
    12971372                "5833": "GeneDB_Pfalciparum",  # Plasmodium falciparum 
    12981373                "4754": None,  # Pneumocystis carinii 
    1299                 "10116": "rgd", # Rattus norvegicus 
     1374                "10116": "rgd",  # Rattus norvegicus 
    13001375                "4932": "sgd",  # Saccharomyces cerevisiae 
    1301                 "4896": "GeneDB_Spombe", # Schizosaccharomyces pombe 
    1302                 "31033": None, # Takifugu rubripes 
     1376                "4896": "GeneDB_Spombe",  # Schizosaccharomyces pombe 
     1377                "31033": None,  # Takifugu rubripes 
    13031378                "8355": None,  # Xenopus laevis 
    1304                 "4577": None # Zea mays 
     1379                "4577": None  # Zea mays 
    13051380                } 
    13061381    version = 1 
    13071382    __shared_state = {"tax": None} 
     1383 
    13081384    def __init__(self): 
    13091385        self.__dict__ = self.__shared_state 
    13101386        if not self.tax: 
    1311             from Orange.orng import orngServerFiles 
    13121387            path = orngServerFiles.localpath_download("GO", "taxonomy.pickle") 
    13131388            if os.path.isfile(path): 
     
    13161391                orngServerFiles.download("GO", "taxonomy.pickle") 
    13171392                self.tax = cPickle.load(open(path, "rb")) 
    1318                  
     1393 
    13191394    def __getitem__(self, key): 
    13201395        key = self.common_org_map.get(key, key) 
    13211396        return self.code_map[key] 
    1322      
     1397 
    13231398    def keys(self): 
    13241399        return list(set(self.common_org_map.keys() + self.code_map.keys())) 
    1325      
    1326 #    @classmethod 
    1327 #    def get_taxonomy(cls): 
    1328 #        import urllib2 as url 
    1329 #        import sgmllib 
    1330 #        organisms 
    1331 #        class MyParser(sgmllib.SGMLParser): 
    1332 #            inTable = False 
    1333 #            def start_table(self, attributes): 
    1334 #                self.inTable = dict(attributes).get("summary", False) 
    1335 #            def end_table(self): 
    1336 #                self.inTable = False 
    1337 #            def start 
    1338      
     1400 
     1401 
    13391402def from_taxid(id): 
    13401403    """ Return a set of GO organism codes that correspond to NCBI taxonomy id 
    13411404    """ 
    13421405    return Taxonomy()[id] 
     1406 
    13431407 
    13441408def to_taxid(db_code): 
     
    13471411    r = [key for key, val in Taxonomy().code_map.items() if db_code == val] 
    13481412    return set(r) 
    1349      
     1413 
    13501414 
    13511415class __progressCallbackWrapper: 
    13521416    def __init__(self, callback): 
    13531417        self.callback = callback 
     1418 
    13541419    def __call__(self, bCount, bSize, fSize): 
    13551420        fSize = 10000000 if fSize == -1 else fSize 
    1356         self.callback(100*bCount*bSize/fSize) 
    1357          
     1421        self.callback(100 * bCount * bSize / fSize) 
     1422 
    13581423from .obiGenomicsUpdate import Update as UpdateBase 
    13591424 
    1360 import urllib2 
    13611425 
    13621426class Update(UpdateBase): 
    13631427    def __init__(self, local_database_path=None, progressCallback=None): 
    13641428        UpdateBase.__init__(self, local_database_path or getDataDir(), progressCallback) 
     1429 
    13651430    def CheckModified(self, addr, date=None): 
    13661431        return date < self.GetLastModified(addr) if date else True 
    1367          
     1432 
    13681433    def CheckModifiedOrg(self, org): 
    13691434        return self.CheckModified("http://www.geneontology.org/gene-associations/gene_association." + org + ".gz", self.LastModifiedOrg(org)) 
    1370      
     1435 
    13711436    def LastModifiedOrg(self, org): 
    13721437        return self.shelve.get((Update.UpdateAnnotation, (org,)), None) 
     
    13891454        elif func == Update.UpdateAnnotation: 
    13901455            return self.CheckModifiedOrg(args[0]) 
    1391              
     1456 
    13921457    def GetDownloadable(self): 
    13931458        orgs = set(self.GetAvailableOrganisms()) - set(self.GetDownloadedOrganisms()) 
     
    14061471        Annotations.DownloadAnnotations(org, os.path.join(self.local_database_path, "gene_association." + org + ".tar.gz"), self.progressCallback) 
    14071472        self._update(Update.UpdateAnnotation, (org,), self.GetLastModified("http://www.geneontology.org/gene-associations/gene_association." + org + ".gz")) 
    1408          
     1473 
    14091474    def UpdateTaxonomy(self, org): 
    14101475        exclude = ["goa_uniprot", "goa_pdb", "GeneDB_tsetse", "reactome", "goa_zebrafish", "goa_rat", "goa_mouse"] 
     
    14191484                a = obiGO.Annotations(os.path.join(self.local_database_path, "gene_association." + org + ".tar.gz")) 
    14201485                taxons = set(ann.taxon for ann in a.annotations) 
    1421                 for taxId in [t.split(":")[-1] for t in taxons if "|" not in t]: ## exclude taxons with cardinality 2 
     1486                for taxId in [t.split(":")[-1] for t in taxons if "|" not in t]:  # exclude taxons with cardinality 2 
    14221487                    tax[taxId].add(org) 
    14231488            except Exception, ex: 
    14241489                print ex 
    1425                  
     1490 
    14261491        cPickle.dump(dict(tax), open(os.path.join(path, "taxonomy.pickle"), "wb")) 
    1427              
     1492 
    14281493 
    14291494def _test1(): 
     
    14341499    o = Ontology("ontology_arch.tar.gz") 
    14351500    a = Annotations("annotations_arch.tar.gz", ontology=o) 
    1436      
    1437     a.GetEnrichedTerms(sorted(a.geneNames)[:100])#, progressCallback=_print) 
     1501 
     1502    a.GetEnrichedTerms(sorted(a.geneNames)[:100])  # , progressCallback=_print) 
    14381503##    profile.runctx("a.GetEnrichedTerms(sorted(a.geneNames)[:100])", {"a":a}, {}) 
    1439     a.GetEnrichedTerms(sorted(a.geneNames)[:100])#, progressCallback=_print) 
    1440     d1 = a.GetEnrichedTerms(sorted(a.geneNames)[:1000])#, progressCallback=_print) 
    1441      
     1504    a.GetEnrichedTerms(sorted(a.geneNames)[:100])  # , progressCallback=_print) 
     1505    d1 = a.GetEnrichedTerms(sorted(a.geneNames)[:1000])  # , progressCallback=_print) 
     1506 
    14421507##    print a.GetEnrichedTerms(sorted(a.geneNames)[:100])#, progressCallback=_print) 
     1508 
    14431509 
    14441510def _test2(): 
     
    14521518        print i 
    14531519#    a.DrawEnrichmentGraph(filterByPValue(terms), len(clusterGenes), len(a.geneNames)) 
    1454                
     1520 
    14551521##    drawEnrichmentGraph([("bal", 1.0, 5, 6, 0.1, 0.4, ["vv"]), 
    14561522##                        ("GO:0019079", 0.5, 5, 6, 0.1, 0.4, ["cc", "bb"]), 
    14571523##                        ("GO:0022415", 0.4, 5, 7, 0.11, 0.4, ["cc1", "bb"])], open("graph.png", "wb"), None, None) 
     1524 
    14581525 
    14591526def _test3(): 
     
    14631530    clusterGenes = sorted(a.geneNames)[:1] + sorted(a.geneNames)[-1:] 
    14641531##    clusterGenes = [g + "_" + str(i%5) for g in sorted(a.geneNames)[:2]] 
    1465     exonMap = dict([(gene, [gene+"_E%i" %i for i in range(10)]) for gene in a.geneNames]) 
     1532    exonMap = dict([(gene, [gene + "_E%i" % i for i in range(10)]) for gene in a.geneNames]) 
    14661533    a.RemapGenes(exonMap) 
    14671534##    o.reverseAliasMapper = o.aliasMapper = {} 
     
    14711538##    a.DrawEnrichmentGraph(filterByPValue(terms), len(clusterGenes), len(a.geneNames)) 
    14721539    a.DrawEnrichmentGraph(filterByPValue(terms, maxPValue=0.1), len(clusterGenes), len(a.geneNames)) 
    1473      
     1540 
    14741541if __name__ == "__main__": 
    14751542    _test2() 
Note: See TracChangeset for help on using the changeset viewer.