################################################################################################### # Facade to JEP: Embedded Python ################################################################################################### #Matplotlib won't work out of the box because it's default backend (Qt) uses signals, which only works in #the main thread. Ideally should find a fix, in order to mark the running thread as the main. #As a workaround, one can use the Tk backend: # #import matplotlib #matplotlib.use('TkAgg') #In principle just add JEP jar and library to the extensions folder. # #Alternatively on Linux: # Python 2: # - Add /lib/python3.X/site-packages/jep to LD_LIBRARY_PATH # - Add /lib/python3.X/site-packages/jep/jep-X.X.X.jar to the class path # #Python3: # - Add JEP library folder to LD_LIBRARY_PATH # - If using OpenJDK, add also python /lib folder to LD_LIBRARY_PATH # - Set LD_PRELOAD=/lib/libpython3.5m.so import sys import os import jep.Jep import jep.SharedInterpreter import jep.NDArray import java.lang.Thread import org.python.core.PyArray as PyArray import java.lang.String as String import java.util.List import java.util.Map import java.util.HashMap import ch.psi.pshell.scripting.ScriptUtils as ScriptUtils from startup import to_array, get_context, _get_caller, Convert, Arr __jep = {} def __get_jep(): t = java.lang.Thread.currentThread() if not t in __jep: init_jep() return __jep[t] def __close_jep(): t = java.lang.Thread.currentThread() if t in __jep: __jep[t].close() def init_jep(): #TODO: Should do it but generates errors #__close_jep() j = jep.SharedInterpreter() try: #Faster, but statements must be complete j.setInteractive(False) except: pass # Removed in 4.2 __jep[java.lang.Thread.currentThread()] = j j.eval("import sys") #sys.argv is not present in JEP and may be needed for certain modules (as Tkinter) j.eval("sys.argv = ['PShell']"); #Add standard script path to python path j.eval("sys.path.append('" + get_context().setup.getScriptPath() + "')") #Redirect stdout j.eval("class JepStdout:\n" + " def write(self, str):\n" + " self.str += str\n" + " def clear(self):\n" + " self.str = ''\n" + " def flush(self):\n" + " pass\n") j.eval("sys.stdout=JepStdout()"); j.eval("sys.stderr=JepStdout()"); j.eval("sys.stdout.clear()") j.eval("sys.stderr.clear()") #Import reload on Python 3 j.eval("try:\n" + " reload # Python 2.7\n" + "except NameError:\n" + " try:\n" + " from importlib import reload # Python 3.4+\n" + " except ImportError:\n" + " from imp import reload # Python 3.0 - 3.3\n") def __print_stdout(): j=__get_jep() output = None err = None try: output = j.getValue("sys.stdout.str") err = j.getValue("sys.stderr.str") j.eval("sys.stdout.clear()") j.eval("sys.stderr.clear()") except: pass if (output is not None) and len(output)>0: print output if (err is not None) and len(err)>0: print >> sys.stderr, err def run_jep(script_name, vars = {}): global __jep script = get_context().scriptManager.library.resolveFile(script_name) if script is None : script= os.path.abspath(script_name) j=__get_jep() for v in vars: j.set(v, vars[v]) try: j.runScript(script) finally: __print_stdout() def eval_jep(line): j=__get_jep() try: j.eval(line) finally: __print_stdout() def set_jep(var, value): j=__get_jep() j.set(var, value) def get_jep(var): j=__get_jep() return j.getValue(var) def call_jep(module, function, args = [], kwargs = {}, reload=False): j=__get_jep() if "/" in module: script = get_context().scriptManager.library.resolveFile(module) if "\\" in script: #Windows paths module_path = script[0:script.rfind("\\")] module = script[script.rfind("\\")+1:] else: #Linux paths module_path = script[0:script.rfind("/")] module = script[script.rfind("/")+1:] eval_jep("import sys") eval_jep("sys.path.append('" + module_path + "')") if module.endswith(".py"): module = module[0:-3] f = module+"_" + function+"_"+str(j.hashCode()) try: if reload: eval_jep("import " + module) eval_jep("_=reload(" + module+")") eval_jep("from " + module + " import " + function + " as " + f) if (kwargs is not None) and (len(kwargs)>0): #invoke with kwargs only available in JEP>3.8 hm=java.util.HashMap() hm.update(kwargs) #The only way to get the overloaded method... m = j.getClass().getMethod("invoke", [String, ScriptUtils.getType("[o"), java.util.Map]) ret = m.invoke(j, [f, to_array(args,'o'), hm]) else: ret = j.invoke(f, args) finally: __print_stdout() return ret #Converts pythonlist or Java array to numpy array def to_npa(data, dimensions = None, type = None): if (not isinstance(data, PyArray)) or (type is not None): data = to_array(data,'d' if type is None else type) if dimensions is None: return jep.NDArray(data) return jep.NDArray(data, dimensions) #recursivelly converts all NumPy arrays to Java arrys def rec_from_npa(obj): if isinstance(obj, jep.NDArray): ret = obj.data if len(obj.dimensions)>1: ret=Convert.reshape(ret, obj.dimensions) return ret if isinstance(obj, java.util.List) or isinstance(obj,tuple) or isinstance(obj,list): ret=[] for i in range(len(obj)): ret.append(rec_from_npa(obj[i])) if isinstance(obj,tuple): return type(ret) return ret if isinstance(obj, java.util.Map) or isinstance(obj,dict): ret = {} if isinstance(obj,dict) else java.util.HashMap() for k in obj.keys(): ret[k] = rec_from_npa(obj[k]) return ret return obj #recursivelly converts all Java arrays to NumPy arrys def rec_to_npa(obj): if isinstance(obj, PyArray): dimensions = Arr.getShape(obj) if len(dimensions)>1: obj = Convert.flatten(obj) return to_npa(obj, dimensions = dimensions) if isinstance(obj, java.util.List) or isinstance(obj,tuple) or isinstance(obj,list): ret=[] for i in range(len(obj)): ret.append(rec_to_npa(obj[i])) if isinstance(obj,tuple): return tuple(ret) return ret if isinstance(obj, java.util.Map) or isinstance(obj,dict): ret = {} if isinstance(obj,dict) else java.util.HashMap() for k in obj.keys(): ret[k] = rec_to_npa(obj[k]) return ret return obj def call_py(module, function, reload_function, *args, **kwargs): """ Calls a CPython function recursively crecursively converting Java arrays in arguments to NumPy, and NumPy arrays in return values to Java arrays. """ ret = call_jep(module, function, rec_to_npa(args), rec_to_npa(kwargs), reload=reload_function) return rec_from_npa(ret) def import_py(module, function): """ Adds a CPython function to globals, creating a wrapper call to JEP, with recurvive convertion of Java arrays in arguments to NumPy arrays, and NumPy arrays in return values to Java arrays. """ def jep_wrapper(*args, **kwargs): reload_function = jep_wrapper.reload jep_wrapper.reload = False print module, function, reload_function return call_py(module, function, reload_function, *args, **kwargs) jep_wrapper.reload=True _get_caller().f_globals[function] = jep_wrapper return jep_wrapper import_py("CPython/linfit", "linfit") import_py("CPython/gfitoff", "gfitoff") x=[0,1,2,3,4,5,6,7,8,9] y=[1,2,3,6,9,6,3,2,1,0] (p, x_fit, y_fit, R2) = linfit(x,y) #print "Fit: ", (p, x_fit, y_fit, R2) plot((y,y_fit), name=("data", "fit"),xdata=(x,x_fit)) from mathutils import Gaussian x=to_array([-200.30429237268825, -200.2650700434188, -200.22115208318002, -199.9457671375377, -199.86345548879072, -199.85213073174933, -199.35687977133284, -199.13811861090275, -197.97304970346386, -197.2952215624348, -195.09076092936948, -192.92276048970703, -191.96871876227698, -189.49577852322938, -187.9652790409825, -183.63756456925222, -180.04899765472996, -178.43839623242422, -174.07311671294445, -172.0410133577918, -165.90824309893102, -160.99771795989466, -159.30176653939253, -154.27688897558514, -152.0854103810786, -145.75652847587313, -140.80843828908465, -139.23982133191495, -134.27073891256106, -132.12649284133064, -125.95947209775511, -121.00309550337462, -119.26736932643232, -114.2706655484383, -112.07393889578914, -105.72295990367157, -100.8088439880125, -99.2034906238494, -94.30042325164636, -92.15010048151461, -85.92203653534293, -81.03913275494665, -79.27412793784428, -74.33487658582118, -72.06274362408762, -65.76562628131825, -60.91255356825276, -59.20334389560392, -54.33286972659312, -52.19387171350535, -45.94978737932291, -41.03014719193582, -39.301602568238906, -34.35572209014114, -32.04464301272608, -25.8221033382824, -20.922074315528747, -19.21590299233186, -14.31090212502093, -12.217203140101386, -5.9283722049240435, -0.9863587170369246, 0.7408048387279834, 5.71126832601389, 7.972628957879352, 14.204559894256546, 19.11839959633025, 20.8218087836657, 25.678748486941828, 27.822718344586864, 34.062659474970715, 38.9745656819391, 40.77409719734158, 45.72080631619803, 47.974156754056835, 54.23453768983539, 59.12020360609568, 60.77306570712026, 65.70734521458867, 67.8344660434617, 74.03187028154134, 78.96532114824849, 80.76070945985495, 85.74802197591286, 87.9140889204674, 94.18082276873524, 99.25790470037091, 100.68454787413205, 105.7213026221542, 107.79483801526698, 113.99555681638138, 119.0707052529143, 120.72715813056156, 125.77551384921307, 127.91257836719551, 134.2011330887875, 139.23043006997628, 140.71673537840158, 145.76288138835983, 147.80216629676042, 154.06420451405637, 159.0846626604798, 160.76183155710717, 165.73699067536242, 167.9265357747636, 173.96705069576544, 178.2522282751915, 179.9042617354548, 183.54586165856657, 185.23269803071796, 189.41678143751972, 191.87149157986588, 192.8741468985015, 195.0241934550453, 195.966634211846, 197.9821647518146, 198.99006812859284, 199.33202054855676, 199.91897441965887, 200.11536227958896, 200.22280936469997, 200.25181179127208],'d') y=to_array([11.0, 6.0, 8.0, 5.0, 11.0, 7.0, 18.0, 11.0, 12.0, 10.0, 8.0, 6.0, 16.0, 4.0, 12.0, 9.0, 15.0, 14.0, 8.0, 20.0, 15.0, 8.0, 9.0, 11.0, 13.0, 12.0, 13.0, 15.0, 13.0, 20.0, 10.0, 7.0, 17.0, 11.0, 20.0, 13.0, 13.0, 23.0, 14.0, 10.0, 17.0, 15.0, 20.0, 16.0, 14.0, 13.0, 18.0, 22.0, 9.0, 20.0, 12.0, 14.0, 17.0, 19.0, 14.0, 14.0, 23.0, 19.0, 15.0, 20.0, 20.0, 21.0, 20.0, 23.0, 22.0, 15.0, 10.0, 17.0, 21.0, 15.0, 23.0, 23.0, 25.0, 18.0, 16.0, 21.0, 22.0, 16.0, 16.0, 14.0, 19.0, 20.0, 18.0, 20.0, 23.0, 13.0, 16.0, 20.0, 25.0, 15.0, 15.0, 17.0, 22.0, 26.0, 19.0, 30.0, 25.0, 17.0, 17.0, 23.0, 16.0, 27.0, 21.0, 21.0, 26.0, 27.0, 21.0, 17.0, 20.0, 20.0, 21.0, 19.0, 25.0, 19.0, 13.0, 23.0, 20.0, 20.0, 18.0, 20.0, 19.0, 25.0],'d') [off, amp, com, sigma] = gfitoff(x, y, off=None, amp=None, com=None, sigma=None) #print "Fit: ", [off, amp, com, sigma] g = Gaussian(amp, com, sigma) plot([y, [g.value(i)+off for i in x]], ["data", "fit"], xdata = x)