source: orange-bioinformatics/orangecontrib/bio/obiGenomicsUpdate.py @ 1873:0810c5708cc5

Revision 1873:0810c5708cc5, 6.7 KB checked in by Ales Erjavec <ales.erjavec@…>, 6 months ago (diff)

Moved '_bioinformatics' into orangecontrib namespace.

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
200def firstUpdateQt():
201    pass
202   
Note: See TracBrowser for help on using the repository browser.