annotate lib/r2py.py @ 0:1d1b9e1b2e2f draft

Uploaded
author petr-novak
date Thu, 19 Dec 2019 10:24:45 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
1 #!/usr/bin/env python3
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
2 import os
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
3 import atexit
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
4 import socket
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
5 import time
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
6 import config
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
7 import pyRserve
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
8
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
9 def shutdown(port):
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
10 try:
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
11 conn = pyRserve.connect(port=port)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
12 print("Shutting down Rserv...", end="")
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
13 conn.shutdown()
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
14 print("Done")
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
15 except pyRserve.rexceptions.RConnectionRefused:
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
16 print("connection to Rserve refused, server is probably already down")
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
17
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
18 def get_open_port():
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
19 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
20 s.bind(("", 0))
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
21 s.listen(1)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
22 port = s.getsockname()[1]
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
23 s.close()
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
24 return port
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
25
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
26 # find free port
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
27 def create_connection():
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
28 '''Start R Rserver and test connection, port is
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
29 stored in config.RSERVE_PORT
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
30 '''
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
31 config.RSERVE_PORT = get_open_port()
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
32 print('Trying to start Rserve...',)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
33 os.system(
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
34 "R CMD Rserve --RS-port {} -q --no-save ".format(config.RSERVE_PORT))
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
35 # wait for server to start accepting connections
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
36 time.sleep(1)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
37 try:
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
38 conn = pyRserve.connect(port=config.RSERVE_PORT)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
39 print("connection OK")
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
40 conn.close()
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
41 atexit.register(shutdown, config.RSERVE_PORT)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
42 return config.RSERVE_PORT
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
43 except:
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
44 print("Connection with Rserve was not established!")
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
45 raise
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
46
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
47
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
48 class setFunctionName():
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
49 # decorator
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
50
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
51 def __init__(self, f, name):
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
52 self.f = f
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
53 self.name = name
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
54
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
55 def __call__(self, *args, **kwargs):
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
56 return self.f(self.name, *args, **kwargs)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
57
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
58
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
59 def convert_types(fn):
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
60 ''' decorator function to convert type for r2py'''
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
61 allowed_classes = [str, int, float, list, bool, type(None)]
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
62 # everything else is converted to str
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
63
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
64 def fn_wrapper(*args, **kwargs):
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
65 new_args = list(args)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
66 new_kwargs = kwargs
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
67 for i, value in enumerate(args):
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
68 if any(type(value) is i for i in allowed_classes):
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
69 new_args[i] = value
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
70 else:
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
71 new_args[i] = str(value)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
72 for i, value in kwargs.items():
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
73 if any(type(value) is i for i in allowed_classes):
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
74 new_kwargs[i] = value
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
75 else:
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
76 new_kwargs[i] = str(value)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
77 return fn(*new_args, **new_kwargs)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
78
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
79 return fn_wrapper
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
80
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
81
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
82 class R():
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
83
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
84 def __init__(self, source, verbose=False):
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
85 ''' Code in file should defined R functions which will be linked to python function
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
86 purpose of this is to make it memory efficient - rserve connection will be closed
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
87 after every exetion so memory is released.
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
88 warning - Source code is executed each time function is used so it should only
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
89 contain function definition!!
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
90
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
91 '''
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
92 self.source = os.path.realpath(source)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
93 conn = pyRserve.connect(port=config.RSERVE_PORT)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
94 conn.voidEval("source('{}', chdir=TRUE)".format(self.source))
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
95 # if single object is define then fn return str! conversion neccessary
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
96 object_names = list(conn.r.ls())
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
97 if verbose:
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
98 print("R function loaded:", end=" ")
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
99 for i in object_names:
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
100 ## skip these objects - not compatible with older version of rserve
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
101 ## and not needed to be accessed from python
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
102 if i in ['DT_OPTIONS', 'HTMLHEADER', 'WD', 'options',
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
103 'htmlheader', 'options', 'xcolor_code', 'TANDEM_RANKS', 'RANKS_TANDEM',]:
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
104 continue
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
105 try:
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
106 obj = getattr(conn.r, i)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
107 if isinstance(obj, pyRserve.rconn.RFuncProxy):
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
108 if verbose:
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
109 print(i, end=" ")
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
110 @convert_types
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
111 def rwrapper(fname, *args, **kwargs):
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
112 c = pyRserve.connect(port=config.RSERVE_PORT)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
113 c.r.setwd(os.getcwd())
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
114 c.voidEval("source('{}',chdir=TRUE)".format(self.source))
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
115 fn = getattr(c.r, fname)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
116 out = fn(*args, **kwargs)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
117 c.close()
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
118 return out
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
119 rwrapper = setFunctionName(rwrapper, i)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
120 setattr(self, i, rwrapper)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
121 del(rwrapper)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
122 except:
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
123 print("skipping :", i)
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
124 pass
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
125 if verbose:
1d1b9e1b2e2f Uploaded
petr-novak
parents:
diff changeset
126 print("\r")