source: orange-bioinformatics/Orange/bioinformatics/obiGenomicsUpdate.py @ 1632:9cf919d0f343

Revision 1632:9cf919d0f343, 7.1 KB checked in by mitar, 2 years ago (diff)

Fixing imports.

Line 
1from __future__ import absolute_import, with_statement
2
3import os
4import shelve
5import datetime
6import tarfile
7import pickle
8from UserDict import DictMixin
9
10from Orange.orng import orngServerFiles
11
12class UpdateShelve(DictMixin):
13    def __init__(self, path):
14        self.__shelve = shelve.open(path)
15
16    def __expand(self, (func, args)):
17        return func.im_class, func.__name__, args
18
19    def __collapse(self, (class_, funcname, args)):
20        return getattr(class_, funcname), args
21
22    def __dumps(self, arg):
23        return pickle.dumps(self.__expand(arg))
24
25    def __loads(self, arg):
26        return self.__collapse(pickle.loads(arg))
27       
28    def __getitem__(self, arg):
29        return self.__shelve.__getitem__(self.__dumps(arg))
30
31    def __setitem__(self, arg, val):
32        self.__shelve.__setitem__(self.__dumps(arg), val)
33
34    def __delitem__(self, arg):
35        self.__shelve.__delitem__(self.__dumps(arg))
36
37    def keys(self):
38        return [self.__loads(key) for key in self.__shelve.keys()]
39
40    def __contains__(self, arg):
41        return self.__shelve.__contains__(self.__dumps(arg))
42
43    def __iter__(self):
44        for key in self.__shelve:
45            yield self.__loads(key)
46
47    def iteritems(self):
48        for key, val in self.__shelve.iteritems():
49            yield self.__loads(key), val
50
51    def sync(self):
52        self.__shelve.sync()
53           
54from threading import Lock
55from functools import wraps
56
57def synchronized(lock):
58    def syncfunc(func):
59        @wraps(func)
60        def f(*args, **kwargs):
61            with lock:
62                return func(*args, **kwargs)
63        return f
64    return syncfunc
65
66from datetime import datetime
67
68class Update(object):
69    def __init__(self, local_database_path, progressCallback=None):
70        """Base update object.
71        Each obi module that uses updatable resources should subclass this class and at minimum reimplement
72        the IsUpdatable and GetDownloadable methods.
73        """
74        self.local_database_path = local_database_path
75        self.progressCallback = progressCallback
76        import os
77        try:
78            os.mkdir(self.local_database_path)
79        except:
80            pass
81        self.shelve = UpdateShelve(os.path.join(self.local_database_path, ".updates.shelve"))
82
83    def IsUpdatable(self, *args):
84        """Return True if the local can be updated else return False
85        """
86        raise NotImplementedError
87   
88    def GetLocal(self):
89        """Return a list [(callable, args), ...] that have been called in the past.
90        """
91        return self.shelve.keys()
92   
93    def GetUpdatable(self):
94        """Return a list [(callable, args), ...] that can be updated.
95        """
96        return [item for item in self.GetLocal() if self.IsUpdatable(*item)]
97       
98    def GetDownloadable(self):
99        """Return a list [(callable, args), ...] that can be downloaded. Must no contain any
100        (callable, args) that are returnd by GetLocal.
101        """
102        raise NotImplementedError
103   
104    def GetLastUpdateTime(self, callable, args):
105        """Returns the last update time of callable with args.
106        """
107        return self.shelve.get((callable, args), datetime(1,1,1))
108
109    def _update(self, callable, args, date=None):
110        """Insert the record of update with date. if date is None use the current date.
111        """
112        self.shelve[callable, args] = date if date else datetime.now()
113        self.shelve.sync()
114
115from Orange.orng import orngServerFiles
116
117class PKGUpdate(Update):
118    def __init__(self, domain, wrappedUpdater, *args, **kwargs):
119        """Wrap the subclass of Update to download data as packages from our own server.
120        Arguments:
121            - domain : should be a string that identifies a resource e.g. "kegg", "go" ...
122            - wrappedUpdater : instance of a subclass of Update that is wrapped
123        Example:
124        >>> pkg = PKGUpdate("go", obiGO.Update())
125        >>> for item in pkg.GetUpdatable():
126        ...     pkg.Apply(*item)
127        ...
128        >>>
129        """
130        Update.__init__(self, wrappedUpdater.local_database_path, wrappedUpdater.progressCallback)
131        self.domain = domain
132        self.serverFiles = orngServerFiles.ServerFiles()
133        self.wrappedUpdater = wrappedUpdater
134        self.wrappedUpdaterClass = wrappedUpdater.__class__
135
136    def _GetServerFileName(self, func, args):
137        return func.__name__+ ("_" + str(args) if args else "") + ".tar.gz"
138
139    def _GetServerDateTime(self, *args):
140        time = self.serverFiles.info(self.domain, self._GetServerFileName(*args))["datetime"].split(".")[0]
141        return datetime.strptime(time, "%Y-%m-%d %H:%M:%S")
142   
143    def IsUpdatable(self, *args):
144        try:
145            return args in self.shelve and self.GetLastUpdateTime(*args) < self._GetServerDateTime(*args)
146        except Exception:
147            return False
148       
149    def GetDownloadable(self):
150        files = self.serverFiles.listfiles(self.domain)
151        downloadable = []
152        for filename in files:
153            if "_" in filename:
154                funcname, args = filename.split("_",1)
155                args = args.split(".")[0]
156                args = eval(args) 
157            else:
158                funcname, args = filename.split(".")[0], ()
159            downloadable.append((getattr(self.wrappedUpdaterClass, funcname), args))
160        return [item for item in downloadable if item not in self.shelve]
161
162    def UpdateWrapper(self, func):
163        @wraps(func)
164        def update(*args):
165            filename = self._GetServerFileName(func, args)
166            time = self._GetServerDateTime(func, args)
167            orngServerFiles.download(self.domain, filename)
168            filepath = orngServerFiles.localpath(self.domain, filename)
169            tar = tarfile.open(filepath)
170            tar.extractall(self.local_database_path)
171            self._update(func, args, time)
172        return update
173
174    def Apply(self, func, args):
175        """Use this method to apply a return values of GetUpdatable ... which are unwrapped
176        """
177        if func.im_class == type(self):
178            return func(self, *args)
179        else:
180            return getattr(self, func.__name__)(*args)
181           
182    def __getattr__(self, name):
183        try:
184            return self.UpdateWrapper(getattr(self.wrappedUpdaterClass, name))
185        except AttributeError:
186            raise AttributeError(name)
187
188def firstUpdateConsole():
189    from . import obiKEGG, obiGO, obiGenomicsUpdate
190
191    pkgUpdate = obiGenomicsUpdate.PKGUpdate("go", obiGO.Update())
192
193    print "Updating GO ontology"
194    pkgUpdate.UpdateOntology()
195
196    for org, name in [("goa_human", "Homo sapiens"), ("sgd", "Yeast")]:
197        print "Updating GO anotations for", name
198        pkgUpdate.UpdateAnnotation(org)
199
200    pkgUpdate = obiGenomicsUpdate.PKGUpdate("kegg", obiKEGG.Update())
201
202    print "Updating KEGG taxonomy"
203    pkgUpdate.UpdateTaxonomy()
204
205    print "Updating KEGG orthology"
206    pkgUpdate.UpdateOrthology()
207
208    print "Updating KEGG reference pathways"
209    pkgUpdate.UpdateReference()
210
211    for org, name in [("hsa", "Homo sapiens"), ("sce", "Yeast")]:
212        print "Updating KEGG pathways for", name
213        pkgUpdate.UpdateOrganism(org)
214   
215
216def firstUpdateQt():
217    pass
218   
Note: See TracBrowser for help on using the repository browser.