-
Notifications
You must be signed in to change notification settings - Fork 179
Expand file tree
/
Copy pathflatline.py
More file actions
171 lines (140 loc) · 5.6 KB
/
flatline.py
File metadata and controls
171 lines (140 loc) · 5.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# -*- coding: utf-8 -*-
#
# Copyright 2022-2025 BigML
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Flatline: Class that encapsulates the Flatline expressions interpreter
"""
from javascript import require
class Flatline:
"""A bridge to an underlying nodejs Flatline interpreter.
This class uses JSPyBridge to launch a Nodejs interpreter that loads
Flatline's javascript implementation and allows interaction via
Python constructs.
Example:
Flatline.check_lisp('(+ 1 2)')
Flatline.check_json(["f", 0], dataset=dataset)
"""
__FLATLINEJS = require('./flatline/flatline-node.js')
interpreter = __FLATLINEJS.bigml.dixie.flatline
#pylint: disable=locally-disabled,invalid-name
@staticmethod
def infer_fields(row, prefix=None, offset=None):
"""Utility function generating a mock list of fields.
Usually, checks and applications of Flatline expressions run
in the context of a given dataset's field descriptors, but
during testing it's useful sometimes to provide a mock set of
them, based on the types of the values of the test input rows.
Example:
In[1]: Interpreter.infer_fields([0, 'a label'])
Out[2]: [{'column_number': 0,
'datatype': 'int64',
'id': '000000',
'optype': 'numeric'},
{'column_number': 1,
'datatype': 'string',
'id': '000001',
'optype': 'categorical'}]
"""
result = []
id_ = 0
for v in row:
t = type(v)
optype = 'categorical'
datatype = 'string'
if (t is int or t is float):
optype = 'numeric'
if t is float:
datatype = 'float64'
else:
datatype = 'int64'
id_str = '%06x' % id_
if prefix:
length = len(prefix)
id_str = prefix + id_str[length:]
column = id_
if offset:
column = offset + id_
result.append({'id': id_str,
'optype':optype,
'datatype': datatype,
'column_number': column})
id_ = id_ + 1
return result
@staticmethod
def _dataset(dataset, rows):
"""The dataset argument should be a Dataset that contains the
in_fields information
"""
try:
return {"fields": dataset.in_fields}
except AttributeError:
if len(rows) > 0:
return {'fields': Flatline.infer_fields(rows[0])}
return None
@staticmethod
def defined_functions():
"""A list of the names of all defined Flaline functions"""
return Flatline.interpreter.defined_primitives
@staticmethod
def check_lisp(sexp, fields=None):
"""Checks whether the given lisp s-expression is valid.
Any operations referring to a dataset's fields will use the
information found in fields structure.
"""
r = Flatline.interpreter.evaluate_sexp(sexp, fields, True).valueOf()
return r
@staticmethod
def check_json(json_sexp, fields=None):
"""Checks whether the given JSON s-expression is valid.
Works like `check_lisp` (which see), but taking a JSON
expression represented as a native Python list instead of a
Lisp sexp string.
"""
r = Flatline.interpreter.evaluate_js(json_sexp, fields).valueOf()
return r
@staticmethod
def lisp_to_json(sexp):
""" Auxliary function transforming Lisp to Python representation."""
return Flatline.interpreter.sexp_to_js(sexp)
@staticmethod
def json_to_lisp(json_sexp):
""" Auxliary function transforming Python to lisp representation."""
return Flatline.interpreter.js_to_sexp(json_sexp)
@staticmethod
def apply_lisp(sexp, rows, dataset=None):
"""Applies the given Lisp sexp to a set of input rows.
Input rows are represented as a list of lists of native Python
values. The dataset info should be provided as a Dataset object.
If no dataset is provided, the field characteristics
of the input rows are guessed using `infer_fields`.
"""
return Flatline.interpreter.eval_and_apply_sexp(
sexp,
Flatline._dataset(dataset, rows),
rows)
@staticmethod
def apply_json(json_sexp, rows, dataset=None):
"""Applies the given JSON sexp to a set of input rows.
As usual, JSON sexps are represented as Python lists,
e.g. ["+", 1, 2].
Input rows are represented as a list of lists of native Python
values. The dataset info should be provided as a Dataset object.
If no dataset is provided, the field characteristics
of the input rows are guessed using `infer_fields`.
"""
return Flatline.interpreter.eval_and_apply_js(
json_sexp,
Flatline._dataset(dataset, rows),
rows)