mi@0: #!/usr/bin/env python mi@0: # encoding: utf-8 mi@0: """ mi@0: ComputationCache.py mi@0: mi@0: Created by George Fazekas on 2014-09-21. mi@0: Copyright (c) 2014 . All rights reserved. mi@0: mi@0: These methods can be used to decorate any function with a caching mechanism to avoid repeating long computations during experimentation. mi@0: mi@0: Example: mi@0: mi@0: m = Meta() mi@0: m.cache = True mi@0: m.cache_file_base = "filname-with-unique-parameters.txt" mi@0: mi@0: @with_cache(meta) mi@0: def some_heavy_function(): mi@0: ... lots of computation here... mi@0: return numpy_array mi@0: mi@0: mi@0: Once decorated, some_heavy_function() will only execute once, then the results will be loaded from a file as long as the parametrs mi@0: encoded in cache_file_base don't change. The parameters and function name are appended to the cache file name so the decorator mi@0: is safe to use for multiple computationally intense functions. mi@0: mi@0: The decorator assumes the heavy function returns a singke numpy array or matrix. mi@0: mi@0: """ mi@0: mi@0: import cPickle mi@0: import numpy as np mi@0: from os.path import join, isdir, dirname mi@0: mi@0: class Meta(object): mi@0: __slots__ = ["cache","cache_file_base","cache_location"] mi@0: mi@0: mi@0: def makedir(output_folder) : mi@0: '''Create a directory tree and set privileges to allow acces to multiple users.''' mi@0: if output_folder and not isdir(output_folder) : mi@0: try: mi@0: from os import makedirs mi@0: makedirs(output_folder,0o777) mi@0: except : mi@0: print "Failed to create directory: %s" %output_folder mi@0: import sys mi@0: sys.exit(-1) mi@0: pass mi@0: mi@0: mi@0: '''Generic decorator that caches function execution results.''' mi@0: def with_cache(meta): mi@0: def wrap(func): mi@0: def file_cache(*args, **kwargs): mi@0: if meta.cache : mi@0: file = "Cache-" + meta.cache_file_base + "-f_%s.txt" %func.__name__ mi@0: file = join(getattr(meta,"cache_location",""),file) mi@0: # print func, meta.cache, file mi@0: try : mi@0: print "Loading data from file <%s>" %file mi@0: return np.loadtxt(file) mi@0: except : mi@0: print "Loading from <%s> failed. Computing new results." %file mi@0: makedir(dirname(file)) mi@0: result = func(*args, **kwargs) mi@0: np.savetxt(file,result) mi@0: return result mi@0: else : mi@0: return func(*args, **kwargs) mi@0: return file_cache mi@0: return wrap mi@0: mi@0: def with_pickle_dump(meta): mi@0: def wrap(func): mi@0: def file_cache(*args, **kwargs): mi@0: if meta.cache : mi@0: file = "Cache-" + meta.cache_file_base + "-f_%s-pickle.txt" %func.__name__ mi@0: file = join(getattr(meta,"cache_location",""),file) mi@0: file = file.replace(" ","-") mi@0: # print func, meta.cache, file mi@0: try : mi@0: print "Loading data from file <%s>" %file mi@0: with open(file, 'r') as fh: mi@0: return cPickle.load(fh) mi@0: except : mi@0: print "Loading from <%s> failed. Computing new results." %file mi@0: makedir(dirname(file)) mi@0: result = func(*args, **kwargs) mi@0: with open(file, 'w') as f: mi@0: f.write(cPickle.dumps(result)) mi@0: return result mi@0: else : mi@0: return func(*args, **kwargs) mi@0: return file_cache mi@0: return wrap mi@0: mi@0: