Files
dev/script/tst_jep.py
2024-06-10 10:44:16 +02:00

300 lines
12 KiB
Python

###################################################################################################
# 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 <python home>/lib/python3.X/site-packages/jep to LD_LIBRARY_PATH
# - Add <python home>/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 <python home>/lib folder to LD_LIBRARY_PATH
# - Set LD_PRELOAD=<python home>/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 java.util.ArrayList
import java.util.Collections
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 isinstance(args, java.util.List):
args=list(args)
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):
ret = obj
if isinstance(obj, jep.NDArray):
ret = obj.data
if len(obj.dimensions)>1:
ret=Convert.reshape(ret, obj.dimensions)
elif 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) or obj.getClass().getSimpleName().startswith("Unmodifiable"): #TODO: Is it a good check for immutability?
# ret=tuple(ret)
elif isinstance(obj, java.util.Map) or isinstance(obj,dict):
ret = {}
for k in obj.keys():
ret[k] = rec_from_npa(obj[k])
return ret
#recursivelly converts all Java arrays to NumPy arrays
def rec_to_npa(obj):
ret = obj
if isinstance(obj, PyArray):
dimensions = Arr.getShape(obj)
if len(dimensions)>1:
obj = Convert.flatten(obj)
ret = to_npa(obj, dimensions = dimensions)
elif isinstance(obj, java.util.List) or isinstance(obj,tuple) or isinstance(obj,list):
ret = java.util.ArrayList()
for i in range(len(obj)):
ret.add(rec_to_npa(obj[i]))
#if isinstance(obj,tuple):
# ret = java.util.Collections.unmodifiableList(ret);
elif isinstance(obj, java.util.Map) or isinstance(obj,dict):
ret = java.util.HashMap()
for k in obj.keys():
ret[k] = rec_to_npa(obj[k])
return ret
def call_py(module, function, reload_function, *args, **kwargs):
"""
Calls a CPython function recursively 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
return call_py(module, function, reload_function, *args, **kwargs)
jep_wrapper.reload=True
_get_caller().f_globals[function] = jep_wrapper
return jep_wrapper
"""
eval_jep("from java.lang import System")
eval_jep("s = 'Hello World'");
eval_jep("System.out.println(s)")
eval_jep("print(s)")
eval_jep("print(s[1:-1])")
eval_jep("import numpy")
r1=call_jep("numpy", "ones", [5])
r2=run_jep("cpython/gfitoff")
"""
"""
import_py("CPython/gfitoff", "gfitoff")
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)
"""
import_py("CPython/linfit", "linfit")
import_py("CPython/linfit", "print_dict")
import_py("CPython/linfit", "get_tuple")
import_py("CPython/linfit", "test2")
#x=to_array([0,1,2,3,4,5,6,7,8,9], 'd')
#y=to_array([1,2,3,6,9,6,3,2,1,0], 'd')
x=[0,1,2,3,4,5,6,7,8,9]
y=[1,2,3,6,9,6,3,2,1,0]
x=(0,1,2,3,4,5,6,7,8,9)
y=(1,2,3,6,9,6,3,2,1,0)
a=java.util.ArrayList()
for i in x:
a.add(i)
(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))
print("-----")
t=get_tuple()
d={"a":1, "b":2}
r=print_dict(d)