source: orange-bioinformatics/_bioinformatics/obiGeneMania.py @ 1719:6e8861564778

Revision 1719:6e8861564778, 31.6 KB checked in by markotoplak, 20 months ago (diff)

Fixed update scripts for MeSH, GO, HomoloGene, NCBI_geneinfo, OMIM, PPI. Moved wget to Orange.utils.

Line 
1""" Interface to retrieve gene networks from GeneMANIA server
2
3Example::
4   
5    >>> conn = Connection("http://localhost:8080/genemania")
6    >>> net = conn.retrieve(org="3702", ["PHYB", "ELF3", 'COP1", "SPA1", "FUS9"])
7    >>> net.save("graph.net")
8    >>> net.retrieve(org="3702", genes=["CIP1"], m="bp", r=100).save("CIP1.net")
9
10"""
11
12from __future__ import absolute_import
13
14import urllib2
15import urllib
16import re
17import posixpath
18from xml.dom import minidom
19
20import orange
21
22DEFAULT_SERVER = "http://193.2.72.57:8080/genemania"
23
24_TAX_ID_2_INDEX = {"3702": 1,
25                   "6239": 2,
26                   "7227": 3,
27                   "9606": 4,
28                   "10090": 5,
29                   "4932": 6
30                   }
31class Connection(object):
32    _RE_TOKEN = re.compile(r'<li\s+id\s*=\s*"menu_save"\s*token\s*=\s*"([0-9]+)"><label>Save</label>')
33    _RE_NETWORK_TAB = re.compile(r'^<div\s*id\s*=\s*"networks_tab"\s*class\s*=\s*"tab">*?^</div>', re.MULTILINE)
34    _RE_NETWORK_GROUP_NAMES = re.compile(r'<div\s*class\s*=\s*"network_name"\s*id\s*=\s*"networkGroupName([0-9]+)"\s*>\s*([a-zA-Z0-9_\- ]+)\s*</div>')
35    _RE_NETWORK_NAMES = re.compile(r'<div\s*class\s*=\s*"network_name"\s*id\s*=\s*"networkName([0-9]+)"\s*>\s*([a-zA-Z0-9_\- ]+)\s*</div>')
36
37    def __init__(self, address=DEFAULT_SERVER):
38        """ Construct a Connection instance for GeneMANIA server at `address`
39       
40        :param address: URL address of GeneMANIA server
41        :type address: str
42        """
43        self.address = address
44                 
45       
46    def retrieveXML(self, org="9606", genes=[], m="automatic", r=10, token=None):
47        """ Same as `retrieve` but return the network as an xml string
48        """
49        if token is None:
50            page = self.retrieveHtmlPage(org, genes, m, r)
51#            query = self._queryPage(org, genes, m, r)
52#            stream = urllib2.urlopen(query)
53#            page = stream.read()
54            match = self._RE_TOKEN.findall(page)
55       
56            if match:
57                token = match[0]
58            else:
59                raise ValueError("Invalid query. %s" % self._queryPage(org, genes, m, r))
60       
61        query = self._queryGraph(token)
62        stream = urllib2.urlopen(query)
63        graph = stream.read()
64        self._graph = graph
65        return graph
66   
67    def retrieveHtmlPage(self, org="9606", genes=[], m="automatic", r=10):
68        """ Retrieve the HTML page (contains token to retrieve the graph, network descriptions ...)"
69        """
70        query = self._queryPage(org, genes, m, r)
71        stream = urllib2.urlopen(query)
72        page = stream.read()
73        self._page = page
74        return page
75   
76    def validate(self, org, genes):
77        """ Validate gene names for organism. Return a two
78        tuple, one with known and one with unknown genes
79        """
80       
81        organism = _TAX_ID_2_INDEX.get(org, 1)
82        genes = "; ".join(genes)
83        data = urllib.urlencode([("organism", str(organism)), ("genes", genes)])
84        validatorUrl = posixpath.join(self.address, "validator")
85        stream = urllib2.urlopen(validatorUrl, data)
86        response = stream.read()
87        dom = minidom.parseString(response)
88        return parseValidationResponse(dom)
89       
90       
91       
92    def _queryPage(self, org, genes, m, r):
93        return posixpath.join(self.address, "link?o=%s&g=%s&m=%s&r=%i" % (org, "|".join(genes), m, r)) 
94   
95   
96    def _queryGraph(self, token):
97        return posixpath.join(self.address, "pages/graph.xhtml?token=%s" % token)
98   
99   
100    def retrieve(self, org, genes, m="automatic", r=10):
101        """ Retrieve :class:`Orange.network.Graph` instance representing the network for
102        the query.
103       
104        :param org: NCBI taxonomy identifier (A. thaliana=3702, C. elegans=6239,
105                    D. melanogaster=7227, H. sapiens=9606, M. musculus=10090
106                    S. cerevisiae=4932)
107        :type org: str
108       
109        :param genes: query genes
110        :type genes: list
111       
112        :param m: network combining method; must be one of the following:
113                    * "automatic_relevance": Assigned based on query genes
114                    * "automatic": Automatically selected weighting method
115                       (Default)
116                    * "bp": biological process based
117                    * "mf": molecular function based
118                    * "cc": cellular component based
119                    * "average": equal by data type
120                    * "average_category: equal by network
121        :type m: str
122       
123        :param r: the number of results generated by GeneMANIA (must be in
124                  range 1..100
125        :type r: int
126       
127        .. note:: See `http://193.2.72.57:8080/genemania/pages/help.jsf#section/link`_ for
128            more details on the parameters.
129        """
130        xml = self.retrieveXML(org, genes, m, r)
131        dom = minidom.parseString(xml)
132        graph = parse(dom)
133        return graph
134   
135       
136   
137def parse(DOM):
138    """ Parse the graph DOM as returned from geneMANIA server and return
139    an :class:`Orange.network.Graph` instance.
140   
141    """
142    nodes = DOM.getElementsByTagName("node")
143    edges = DOM.getElementsByTagName("edge")
144    from collections import defaultdict
145    graphNodes = {}
146    graphEdges = defaultdict(list)
147   
148    def parseAttributes(element):
149        return dict([(key, value) for key, value in element.attributes.items()])
150   
151    def parseText(element):
152        text = u""
153        for el in element.childNodes:
154            if isinstance(el, minidom.Text):
155                text += el.wholeText
156        return text
157               
158    def parseData(node):
159        data = node.getElementsByTagName("data")
160        parsed = {}
161        for el in data:
162            attrs = parseAttributes(el)
163            key = attrs["key"]
164            parsed[key] = parseText(el)
165        return parsed
166   
167    for node in nodes:
168        attrs = parseAttributes(node)
169        id = attrs["id"]
170        data = parseData(node)
171        graphNodes[id] = data
172   
173    for edge in edges:
174        attrs = parseAttributes(edge)
175        source, target = attrs["source"], attrs["target"]
176        data = parseData(edge)
177        graphEdges[source, target].append(data)
178       
179    allData = reduce(list.__add__, graphEdges.values(), [])
180    edgeTypes = set([int(data["networkGroupId"]) for data in allData])
181    groupId2int = dict(zip(edgeTypes, range(len(edgeTypes))))
182    groupId2groupCode = dict([(int(data["networkGroupId"]), str(data["networkGroupCode"])) for data in allData])
183    graphNode2nodeNumber = dict(zip(graphNodes, range(len(graphNodes))))
184   
185    import Orange
186    graph = Orange.network.Graph()
187    for id, data in graphNodes.items():
188        graph.add_node(graphNode2nodeNumber[id],
189                       original_id=str(id),
190                       symbol=data["symbol"],
191                       score=float(data["score"]))
192         
193    graph.add_nodes_from(sorted(graphNode2nodeNumber.values()))
194   
195    edgeWeights = []
196    for (source, target), edge_data in graphEdges.items():
197        edgesDefined = [None] * len(edgeTypes)
198        for data in edge_data:
199            networkGroupId = int(data["networkGroupId"])
200            edgeInd = groupId2int[networkGroupId]
201            edgesDefined[edgeInd] = float(data["weight"])
202            graph.add_edge(graphNode2nodeNumber[source], 
203                           graphNode2nodeNumber[target],
204                           weight=float(data["weight"]),
205                           networkGroupId=networkGroupId)
206           
207        edgesDefined = [0 if w is None else w for w in edgesDefined]
208        edgeWeights.append(edgesDefined)
209       
210       
211    nodedomain = orange.Domain([orange.StringVariable("label"),
212                                orange.StringVariable("id"),
213                                orange.FloatVariable("score"),
214                                orange.StringVariable("symbol"),
215                                orange.StringVariable("go"),
216                                orange.EnumVariable("source", values=["true", "false"])], None)
217   
218    edgedomain = orange.Domain([orange.FloatVariable("u"),
219                                orange.FloatVariable("v")] +\
220                               [orange.FloatVariable("weight_%s" % groupId2groupCode[id]) for id in edgeTypes],
221                               None)
222   
223    node_items = graphNodes.items()
224    node_items = sorted(node_items, key=lambda t: graphNode2nodeNumber[t[0]])
225   
226    nodeitems = orange.ExampleTable(nodedomain,
227                  [[str(node["symbol"]), str(id), float(node["score"]),
228                    str(node["symbol"]), str(node["go"]), str(node["source"])]\
229                     for id, node in node_items])
230   
231    edgeitems = orange.ExampleTable(edgedomain,
232                  [[str(graphNode2nodeNumber[source] + 1), 
233                    str(graphNode2nodeNumber[target] + 1)] + weights \
234                   for ((source, target), _), weights in zip(graphEdges.items(), edgeWeights)])
235       
236    graph.set_items(nodeitems)
237    graph.set_links(edgeitems)
238   
239    return graph
240
241def parseValidationResponse(dom):
242    def getData(node):
243        data = []
244        for c in node.childNodes:
245            if c.nodeType == node.TEXT_NODE:
246                data.append(c.data)
247               
248        return " ".join([d.strip() for d in data])
249       
250    def getStrings(node):
251        strings = []
252        for string in node.getElementsByTagName("string"):
253            strings.append(getData(string))
254        return strings
255    errorCode = dom.getElementsByTagName("errorCode")[0]
256    errorCode = getData(errorCode)
257    invalidSymbols = getStrings(dom.getElementsByTagName("invalidSymbols")[0])
258    geneIds = getStrings(dom.getElementsByTagName("geneIds")[0])
259   
260    return errorCode, invalidSymbols, geneIds
261   
262
263from HTMLParser import HTMLParser
264
265class NetworkGroup(object):
266    """ Network group descriptor
267    """
268    def __init__(self):
269        self.weight = ""
270        self.networks = []
271        self.name = ""
272        self.id = ""
273
274
275class Network(object):
276    """ Source network descriptor
277    """
278   
279    def __init__(self):
280        self.weight = ""
281        self.name = ""
282        self.id = ""
283        self.description = ""
284       
285       
286class _NetworkTabParser(HTMLParser):
287    """ Parses the "Network" tab from the GeneMANIA HTML pages
288    """
289    _RE_GROUP_ID = re.compile(r"networkGroup(\d+)")
290    _RE_GROUP_WEIGHT_ID = re.compile(r"networkGroupWeight(\d+)")
291    _RE_GROUP_NAME_ID = re.compile(r"networkGroupName(\d+)")
292   
293    _RE_NETWORK_ID = re.compile(r"network(\d+)")
294    _RE_NETWORK_WEIGHT_ID = re.compile(r"networkWeight(\d+)")
295    _RE_NETWORK_NAME_ID = re.compile(r"networkName(\d+)")
296    _RE_NETWORK_DESCRIPTION_ID = re.compile("networkDescription(\d+)")
297   
298   
299    def __init__(self, *args, **kwargs):
300        HTMLParser.__init__(self)
301        self.networkGroups = []
302        self.networks = {}
303       
304        self.currentGroup = None
305        self.currentNetwork = None
306       
307        self.data_handler = None
308       
309    def handle_start_group(self, tag, attrs):
310        """ Handle '<li class=... id="networkGroup%i">'
311        """
312        self.currentGroup = NetworkGroup()
313        self.currentGroup.id = attrs.get("id")
314       
315        self.networkGroups.append(self.currentGroup)
316       
317       
318    def handle_start_group_weight(self, tag, attrs):
319        """ Handle '<span tooltip="..." id="networkGroupWeight%i">'
320        """
321        self.data_handler = self.handle_group_weight_data
322       
323    def handle_group_weight_data(self, data):
324        self.currentGroup.weight += data
325       
326    def handle_end_group_weight(self, tag):
327        self.data_handler = None
328       
329    def handle_start_group_name(self, tag, attrs):
330        """ Handle '<div class="network_name" id="networkGroupName%i">'
331        """
332        self.data_handler = self.handle_group_name_data
333       
334    def handle_group_name_data(self, data):
335        self.currentGroup.name += data
336       
337    def handle_start_network(self, tag, attrs):
338        """ Handle '<li class="checktree_network" id="network%i">'
339        """
340        self.currentNetwork = Network()
341        self.currentNetwork.id = attrs.get("id")
342       
343        self.currentGroup.networks.append(self.currentNetwork)
344       
345    def handle_start_network_weight(self, tag, attrs):
346        """ Handle '<span tooltip="..." id="networkWeight%i">'
347        """
348        self.data_handler = self.handle_network_weight_data
349       
350    def handle_network_weight_data(self, data):
351        self.currentNetwork.weight += data
352       
353    def handle_start_network_name(self, tag, attrs):
354        """ Handle '<div class="network_name" id="networkName%i">'
355        """
356        self.data_handler = self.handle_network_name_data
357       
358    def handle_network_name_data(self, data):
359        self.currentNetwork.name += data
360       
361    def handle_start_network_description(self, tag, attrs):
362        """ Handle '<div class="text" id="networkDescription%i">'
363        """
364        self.data_handler = self.handle_network_description_data
365       
366    def handle_network_description_data(self, data):
367        self.currentNetwork.description += data
368       
369    def handle_data(self, data):
370        if self.data_handler:
371            self.data_handler(data)
372   
373    def handle_starttag(self, tag, attrs):
374        attrs = dict(attrs)
375        if tag == "li" and self._RE_GROUP_ID.search(attrs.get("id", "")):
376            self.handle_start_group(tag, attrs)
377        elif tag == "span" and self._RE_GROUP_WEIGHT_ID.search(attrs.get("id", "")):
378            self.handle_start_group_weight(tag, attrs)
379        elif tag == "div" and self._RE_GROUP_NAME_ID.search(attrs.get("id", "")):
380            self.handle_start_group_name(tag, attrs)
381        elif tag == "li" and self._RE_NETWORK_ID.search(attrs.get("id", "")):
382            self.handle_start_network(tag, attrs)
383        elif tag == "span" and self._RE_NETWORK_WEIGHT_ID.search(attrs.get("id", "")):
384            self.handle_start_network_weight(tag, attrs)
385        elif tag == "div" and self._RE_NETWORK_NAME_ID.search(attrs.get("id", "")):
386            self.handle_start_network_name(tag, attrs)
387        elif tag == "div" and self._RE_NETWORK_DESCRIPTION_ID.search(attrs.get("id", "")):
388            self.handle_start_network_description(tag, attrs)
389        else:
390            HTMLParser.handle_starttag(self, tag, attrs)
391           
392    def handle_endtag(self, tag):
393        self.data_handler = None
394           
395
396def parsePage(html):
397    parser = _NetworkTabParser()
398    parser.feed(html)
399    return parser.networkGroups
400   
401
402def retrieve(org=None, genes=[], m="automatic", r=10):
403    """ A helper function, same as Connection().retrive(*args, **kwargs)
404    """
405    return Connection().retrieve(org, genes, m, r)
406
407
408"""
409======================
410PPI Database interface
411======================
412
413"""
414
415
416import sqlite3
417import csv
418import os
419import posixpath
420
421from contextlib import contextmanager
422import StringIO
423
424@contextmanager
425def finishing(obj):
426    """ Calls obj.finish() on context exit.
427    """
428    yield obj
429    obj.finish()
430
431def guess_size(fileobj):
432    try:
433        if isinstance(fileobj, file):
434            return os.fstat(fileobj.fileno()).st_size
435        elif isinstance(fileobj, StringIO.StringIO):
436            pos = fileobj.tell()
437            fileobj.seek(0, 2)
438            length = fileobj.tell() - pos
439            fileobj.seek(pos, 0)
440            return length
441        elif isinstance(fileobj, urllib.addinfourl):
442            length = fileobj.headers.get("content-length", None)
443            return length
444    except Exception, ex:
445        pass
446
447from Orange.utils import wget
448   
449from . import obiPPI
450from Orange.orng import orngServerFiles
451
452from . import obiTaxonomy
453from collections import namedtuple
454from operator import itemgetter
455from Orange.utils import lru_cache
456
457GENE_MANIA_INTERACTION_FIELDS = \
458    ["gene_a", "gene_b", "weight", "network_name",
459     "network_group", "source", "pubmed_id"]
460     
461GeneManiaInteraction = namedtuple("GeneManiaInteraction",
462                                  field_names=GENE_MANIA_INTERACTION_FIELDS
463                                 )
464
465import weakref
466class Internalizer(object):
467    """ A class that acts as the python builtin function ``intern``,
468    for as long as it is alive.
469   
470    .. note:: This is for memory optimization only, it does not affect
471        dict lookup speed.
472   
473    """
474    def __init__(self):
475        self._intern_dict = {}
476       
477    def __call__(self, obj):
478        return self._intern_dict.setdefault(obj, obj)
479   
480class GeneManiaDatabase(obiPPI.PPIDatabase):
481    DOMAIN = "PPI"
482    SERVER_FILE = "gene-mania-{taxid}.sqlite"
483   
484    TAXID2NAME = ""
485   
486    # DB schema
487    SCHEMA = """
488    table: `genes`
489        - `internal_id`: int (pk)
490        - `gene_name`: text (preferred name)
491       
492    table: `synonyms`:
493        - `internal_id: int (foreign key `genes.internal_id`)
494        - `synonym`: text
495        - `source_id`: int
496       
497    table: `source`:
498        - `source_id`: int
499        - `source_name`: text
500       
501    table: `links`:
502        - `gene_a`: int (fk `genes.internal_key`)
503        - `gene_b`: int (fk `genes.internal_key`)
504        - `network_id`: (fk `networks.network_id`)
505        - `weight`: real
506       
507    table: `networks`:
508        - `network_id`: int
509        - `network_name`: text
510        - `network_group`: text
511        - `source`: text
512        - `pubmed_id`: text
513       
514    view: `links_annotated`:
515        - `gene_name_a`
516        - `gene_name_b`
517        - `network_name`
518        - `network_group`
519        - `weight`
520       
521    """
522   
523    def __init__(self, taxid):
524        self.taxid = taxid
525       
526    @classmethod
527    def common_taxids(self):
528        return ["3702", "6239", "7227", "9606", "10090", "10116", "4932"]
529   
530    def organisms(self):
531        """ Return all organism taxids contained in this database.
532       
533        .. note:: a single taxid is returned (the one used at
534            instance initialization)   
535       
536        """
537        return [self.taxid]
538   
539    def ids(self, taxid=None):
540        """ Return all primary ids for `taxid`.
541        """
542        if taxid is None:
543            taxids = self.organisms()
544            return reduce(list.__add__, map(self.ids, taxids), [])
545       
546        con = self._db(taxid)
547        cur = con.execute("""\
548            SELECT gene_name FROM genes
549            """)
550        return map(itemgetter(0), cur)
551       
552    def synonyms(self, id):
553        """ Return a list of synonyms for primary `id`.
554        """
555        con = self._db(self.taxid)
556        cur = con.execute("""\
557            SELECT synonyms.synonym
558            FROM synonyms NATURAL LEFT JOIN genes
559            WHERE genes.gene_name=?
560            """, (id,))
561        return map(itemgetter(0), cur)
562       
563    def all_edges(self, taxid=None):
564        """ Return a list of all edges.
565        """
566        con = self._db(self.taxid)
567        cur = con.execute("""
568            SELECT links.gene_a, links.gene_b, links.weight
569            FROM links""")
570        id_to_name = self._gene_id_to_name()
571        return [(id_to_name[r[0]], id_to_name[r[1]], r[2]) \
572                for r in cur]
573       
574    def all_edges_annotated(self, taxid=None):
575        """ Return a list of all edges with all available annotations
576        """
577        con = self._db(self.taxid)
578        cur = con.execute("""\
579            SELECT links.gene_a, links.gene_b, links.weight, links.network_id
580            FROM links""")
581        gene_to_name = self._gene_id_to_name()
582        network_to_description = self._network_id_to_description()
583        res = []
584        for gene_a, gene_b, w, n_id in cur:
585            n_desc = network_to_description[n_id]
586           
587            res.append(GeneManiaInteraction(gene_to_name[gene_a],
588                            gene_to_name[gene_b], w, *n_desc))
589        return res
590       
591    def edges(self, id1):
592        """ Return all edges for primary id `id1`.
593        """       
594        con = self._db(self.taxid)
595        cur = con.execute("""\
596            SELECT genes1.gene_name, genes2.gene_name, links.weight
597            FROM genes AS genes1 
598                JOIN links
599                    ON genes1.internal_id=links.gene_a
600                JOIN genes AS genes2
601                    ON genes2.internal_id=links.gene_b
602            WHERE genes1.gene_name=?
603            """, (id1,))
604        res = cur.fetchall()
605        cur = con.execute("""\
606            SELECT genes1.gene_name, genes2.gene_name, links.weight
607            FROM genes AS genes1 
608                JOIN  links
609                    ON genes1.internal_id=links.gene_a
610                JOIN genes AS genes2
611                    ON genes2.internal_id=links.gene_b
612            WHERE genes2.gene_name=?
613            """, (id1,))
614        res += cur.fetchall()
615       
616        return res
617   
618    def edges_annotated(self, id=None):
619        """ Return a list of annotated edges for primary `id`
620        """
621        con = self._db(self.taxid)
622        cur = con.execute("""\
623            SELECT genes1.gene_name, genes2.gene_name, links.weight,
624                   networks.network_name, networks.network_group,
625                   networks.source, networks.pubmed_id
626            FROM genes AS genes1
627                JOIN  links
628                    ON genes1.internal_id=links.gene_a
629                JOIN genes AS genes2
630                    ON genes2.internal_id=links.gene_b
631                NATURAL JOIN networks
632            WHERE genes1.gene_name=?
633            """, (id,))
634        res = cur.fetchall()
635        cur = con.execute("""\
636            SELECT genes1.gene_name, genes2.gene_name, links.weight,
637                   networks.network_name, networks.network_group,
638                   networks.source, networks.pubmed_id
639            FROM genes AS genes1
640                JOIN links
641                    ON genes1.internal_id=links.gene_a
642                JOIN genes AS genes2
643                    ON genes2.internal_id=links.gene_b
644                NATURAL JOIN networks
645            WHERE genes2.gene_name=?
646            """, (id,))
647        res += cur.fetchall()
648        return [GeneManiaInteraction(*r) for r in res]
649   
650    def search_id(self, name, taxid=None):
651        """ Search the database for gene name. Return a list of matching
652        primary ids. Use `taxid` to limit the results to a single organism.
653       
654        """
655        con = self._db(self.taxid)
656        cur = con.execute("""\
657            SELECT genes.gene_name
658            FROM genes NATURAL JOIN synonyms
659            WHERE synonyms.synonym=?
660            """, (name,))
661        return map(itemgetter(0), cur)
662       
663    def _db(self, taxid=None):
664        """ Return an open sqlite3.Connection object. 
665        """
666        taxid = taxid or self.taxid
667        filename = orngServerFiles.localpath_download("PPI",
668                            self.SERVER_FILE.format(taxid=taxid))
669        if not os.path.exists(filename):
670            raise ValueError("Database is missing.")
671       
672        return sqlite3.connect(filename)
673   
674    @lru_cache(maxsize=1)
675    def _gene_id_to_name(self):
676        """ Return a dictionary mapping internal gene ids to
677        primary gene identifiers.
678       
679        """
680        con = self._db(self.taxid)
681        cur = con.execute("SELECT * FROM genes")
682        return dict(cur)
683   
684    @lru_cache(maxsize=1)
685    def _network_id_to_description(self):
686        """ Return a dictionary mapping internal network ids
687        to (name, group, source, pubmed id).
688         
689        """
690        con = self._db(self.taxid)
691        cur = con.execute("SELECT * FROM networks")
692        return dict((t[0], t[1:]) for t in cur)
693   
694    #####################################
695    # Data download and DB initialization
696    #####################################
697     
698    @classmethod
699    def download_data(cls, taxid=None, progress_callback=None):
700        """ Download the data for ``taxid`` from the GeneMANIA
701        website and initialize the local database.
702       
703        """
704        import tarfile
705       
706        baseurl = "http://genemania.org/data/current/"
707        directory = orngServerFiles.localpath("PPI")
708        if taxid is None:
709            taxid = cls.common_taxids()
710       
711        if isinstance(taxid, (list, tuple)):
712            taxids = taxid
713        else:
714            taxids = [taxid]
715        for taxid in taxids:
716            name = obiTaxonomy.name(taxid)
717            name = name.replace(" ", "_")
718           
719            if progress_callback is None:
720                progress = True #orngServerFiles.ConsoleProgressBar("Downloading %r." % filename)
721            else:
722                progress = progress_callback
723           
724            filename = name + ".tgz"
725            url = baseurl + "networks/" + filename   
726            wget(url, directory=directory, progress=progress)
727           
728            tgz_filename = os.path.join(directory, filename)   
729            tgz = tarfile.open(tgz_filename)
730            tgz.extractall(directory)
731           
732            filename = name + ".COMBINED.tgz"
733            url = baseurl + "precombined/" + filename
734            wget(url, directory=directory, progress=progress)
735           
736            tgz_filename = os.path.join(directory, filename)
737            tgz = tarfile.open(tgz_filename)
738            tgz.extractall(directory)
739       
740            cls.init_db([taxid])
741       
742    @classmethod
743    def init_db(cls, taxid=None):
744        """ Init the local data base.
745        """
746        from functools import partial
747        directory = orngServerFiles.localpath("PPI")
748        pjoin = partial(os.path.join, directory)
749        if taxid is None:
750            taxid = cls.common_taxids()
751           
752        if isinstance(taxid, (list, tuple)):
753            for tid in taxid:
754                cls.init_db(tid)
755            return
756               
757        if not isinstance(taxid, basestring):
758            raise ValueError("wrong taxid")
759           
760#        taxid = taxids
761        name = obiTaxonomy.name(taxid).replace(" ", "_")
762        networks = csv.reader(open(pjoin(name, "networks.txt")), delimiter="\t")
763        networks.next() # Header
764        networks = list(networks)
765       
766        database = pjoin(cls.SERVER_FILE.format(taxid=taxid))
767        with sqlite3.connect(database) as con:
768            con.execute("""DROP TABLE IF EXISTS genes""")
769            con.execute("""DROP TABLE IF EXISTS synonyms""")
770            con.execute("""DROP TABLE IF EXISTS source""")
771            con.execute("""DROP TABLE IF EXISTS links""")
772            con.execute("""DROP TABLE IF EXISTS networks""")
773           
774            con.execute("""DROP INDEX IF EXISTS genes_index""")
775            con.execute("""DROP INDEX IF EXISTS links_index_a""")
776            con.execute("""DROP INDEX IF EXISTS links_index_b""")
777           
778            con.execute("""\
779                CREATE TABLE networks
780                    (network_id INTEGER PRIMARY KEY ASC AUTOINCREMENT,
781                     network_name TEXT,
782                     network_group TEXT,
783                     source TEXT,
784                     pubmed_id TEXT
785                    )""")
786           
787            con.executemany("""\
788                INSERT INTO networks
789                VALUES (?, ?, ?, ?, ?)""", [(i, r[2], r[1], r[3], r[4]) \
790                                        for i, r in enumerate(networks)])
791           
792            con.execute("""\
793                CREATE TABLE genes
794                    (internal_id INTEGER PRIMARY KEY ASC AUTOINCREMENT,
795                     gene_name TEXT
796                    )""")
797           
798            identifiers = csv.reader(open(pjoin(name, "identifier_mappings.txt"), "rb"),
799                                    delimiter="\t")
800            identifiers.next() # skip header
801            identifiers = list(identifiers)
802            genes = sorted(set(r[0] for r in identifiers))
803            sources = sorted(set(r[2] for r in identifiers))
804           
805            con.executemany("""\
806                INSERT INTO genes
807                VALUES (?, ?)""", enumerate(genes))
808           
809            con.execute("""\
810            CREATE TABLE source
811                (source_id INTEGER PRIMARY KEY ASC AUTOINCREMENT,
812                 source_name TEXT
813                )""")
814           
815            con.executemany("""\
816                INSERT INTO source
817                VALUES (?, ?)""", enumerate(sources))
818           
819            con.execute("""\
820                CREATE TABLE synonyms
821                    (internal_id INTEGER REFERENCES genes (internal_id),
822                     synonym TEXT,
823                     source_id INT REFERENCES source (source_id)
824                    )""")
825           
826            gene_to_id = dict((g, i) for i, g in enumerate(genes))
827            source_to_id = dict((s, i) for i, s in enumerate(sources))
828            con.executemany("""\
829                INSERT INTO synonyms
830                VALUES (?, ?, ?)""", [(gene_to_id[r[0]], r[1], source_to_id[r[2]])\
831                                       for r in identifiers])
832           
833            con.execute("""\
834                CREATE TABLE links
835                    (gene_a INTEGER REFERENCES genes (internal_id),
836                     gene_b INTEGER REFERENCES genes (internal_id),
837                     network_id INTEGER REFERENCES networks (network_id),
838                     weight REAL
839                     -- , PRIMARY KEY (gene_a, gene_b, network_id)
840                    )""")
841           
842            for i, (filename, group, _, _, _) in enumerate(networks):
843                nf  = open(pjoin(name, filename), "rb")
844                interactions = csv.reader(nf, delimiter="\t")
845                interactions.next() # skip header
846                con.executemany("""\
847                    INSERT INTO links
848                    VALUES (?, ?, ?, ?)""",
849                    [(gene_to_id[r[0]], gene_to_id[r[1]], i, float(r[2])) \
850                     for r in interactions]
851                )
852               
853            # Add special combined network entry
854            combined_id = len(networks)
855            con.execute("""\
856                INSERT INTO networks
857                VALUES (?, ?, ?, ?, ?)""", 
858                (combined_id, "BP_COMBINING", "COMBINED", "GeneMANIA", ""))
859           
860            # Add the combined network links.
861            combined = open(pjoin(name + ".COMBINED", "COMBINED.DEFAULT_NETWORKS.BP_COMBINING.txt"), "rb")
862            combined = csv.reader(combined, delimiter="\t")
863            combined.next()
864            con.executemany("""\
865                INSERT INTO links
866                VALUES (?, ?, ?, ?)""",
867                    ((gene_to_id[r[0]], gene_to_id[r[1]], combined_id, float(r[2])) \
868                     for r in combined))
869           
870           
871            con.execute("""
872                CREATE VIEW IF NOT EXISTS links_annotated
873                AS SELECT genes1.gene_name AS gene_name_a,
874                          genes2.gene_name AS gene_name_b,
875                          links.weight,
876                          networks.network_name,
877                          networks.network_group,
878                          networks.source,
879                          networks.pubmed_id
880                   FROM  genes AS genes1
881                        JOIN links
882                              ON genes1.internal_id=links.gene_a
883                        JOIN genes AS genes2
884                              ON links.gene_b=genes2.internal_id
885                        JOIN networks
886                              ON links.network_id=networks.network_id
887                    """)
888           
889           
890            con.execute("""\
891                CREATE INDEX IF NOT EXISTS genes_index ON genes (gene_name)
892                """)
893            con.execute("""\
894                CREATE INDEX IF NOT EXISTS links_index_a ON links (gene_a)
895                """)
896            con.execute("""\
897                 CREATE INDEX IF NOT EXISTS links_index_b ON links (gene_b)
898                """)
899       
900           
901if __name__ == "__main__":
902    retrieve("9606", [ 'MRE11A', 'RAD51', 'MLH1', 'MSH2', 'DMC1', 'RAD51AP1', 'RAD50', 'MSH6', 'XRCC3', 'PCNA', 'XRCC2' ])
Note: See TracBrowser for help on using the repository browser.