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

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

Moved '_bioinformatics' into orangecontrib namespace.

RevLine 
[1632]1from __future__ import absolute_import, with_statement
2
[399]3import os
[188]4import shelve
5import datetime
[439]6import tarfile
[447]7import pickle
8from UserDict import DictMixin
[188]9
[1632]10from Orange.orng import orngServerFiles
11
[447]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()
[389]53           
54from threading import Lock
55from functools import wraps
56
57def synchronized(lock):
58    def syncfunc(func):
59        @wraps(func)
[447]60        def f(*args, **kwargs):
61            with lock:
62                return func(*args, **kwargs)
[389]63        return f
64    return syncfunc
65
[447]66from datetime import datetime
67
[450]68class Update(object):
[188]69    def __init__(self, local_database_path, progressCallback=None):
[455]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        """
[188]74        self.local_database_path = local_database_path
75        self.progressCallback = progressCallback
[447]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"))
[188]82
[447]83    def IsUpdatable(self, *args):
[455]84        """Return True if the local can be updated else return False
85        """
[447]86        raise NotImplementedError
87   
88    def GetLocal(self):
[455]89        """Return a list [(callable, args), ...] that have been called in the past.
90        """
[447]91        return self.shelve.keys()
92   
[188]93    def GetUpdatable(self):
[455]94        """Return a list [(callable, args), ...] that can be updated.
95        """
[447]96        return [item for item in self.GetLocal() if self.IsUpdatable(*item)]
97       
[188]98    def GetDownloadable(self):
[455]99        """Return a list [(callable, args), ...] that can be downloaded. Must no contain any
100        (callable, args) that are returnd by GetLocal.
101        """
[439]102        raise NotImplementedError
[188]103   
104    def GetLastUpdateTime(self, callable, args):
[455]105        """Returns the last update time of callable with args.
106        """
[447]107        return self.shelve.get((callable, args), datetime(1,1,1))
[188]108
[439]109    def _update(self, callable, args, date=None):
[455]110        """Insert the record of update with date. if date is None use the current date.
111        """
[447]112        self.shelve[callable, args] = date if date else datetime.now()
[389]113        self.shelve.sync()
[439]114
[1632]115from Orange.orng import orngServerFiles
[439]116
117class PKGUpdate(Update):
[447]118    def __init__(self, domain, wrappedUpdater, *args, **kwargs):
[455]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        """
[447]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
[450]136    def _GetServerFileName(self, func, args):
[447]137        return func.__name__+ ("_" + str(args) if args else "") + ".tar.gz"
138
[450]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   
[447]143    def IsUpdatable(self, *args):
[450]144        try:
145            return args in self.shelve and self.GetLastUpdateTime(*args) < self._GetServerDateTime(*args)
146        except Exception:
[447]147            return False
[450]148       
[439]149    def GetDownloadable(self):
[447]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], ()
[450]159            downloadable.append((getattr(self.wrappedUpdaterClass, funcname), args))
[447]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):
[450]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)
[447]169            tar = tarfile.open(filepath)
170            tar.extractall(self.local_database_path)
[450]171            self._update(func, args, time)
[447]172        return update
173
[454]174    def Apply(self, func, args):
[455]175        """Use this method to apply a return values of GetUpdatable ... which are unwrapped
176        """
[454]177        if func.im_class == type(self):
178            return func(self, *args)
179        else:
180            return getattr(self, func.__name__)(*args)
181           
[447]182    def __getattr__(self, name):
183        try:
184            return self.UpdateWrapper(getattr(self.wrappedUpdaterClass, name))
185        except AttributeError:
186            raise AttributeError(name)
[439]187
[550]188def firstUpdateConsole():
[1632]189    from . import obiKEGG, obiGO, obiGenomicsUpdate
[440]190
[550]191    pkgUpdate = obiGenomicsUpdate.PKGUpdate("go", obiGO.Update())
[439]192
[550]193    print "Updating GO ontology"
194    pkgUpdate.UpdateOntology()
[439]195
[550]196    for org, name in [("goa_human", "Homo sapiens"), ("sgd", "Yeast")]:
197        print "Updating GO anotations for", name
198        pkgUpdate.UpdateAnnotation(org)
[440]199
[550]200def firstUpdateQt():
201    pass
202   
Note: See TracBrowser for help on using the repository browser.