annotate lib/r2py.py @ 10:6212933b1a83 draft

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