-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathlib_numpy.py
More file actions
289 lines (245 loc) · 10.6 KB
/
lib_numpy.py
File metadata and controls
289 lines (245 loc) · 10.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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
import operator, functools
import numpy as np
from model import *
from lib import SimSchema
from sim import Property, Simulator
class NPToArray(SimSchema):
'''Construct an ndarray out of the object I, and emits it at Q.'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NP2AR', [
Connector('I'),
], [
Connector('Q', np.ndarray)
])
def step(self, node):
node.setOut('Q', np.array(node.getIn('I')))
class NPZeroes(SimSchema):
'''Constructs a zero-filled ndarray with shape S and data type T.'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPZRS', [
Connector('S', list),
Connector('T', str),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', np.zeros(node.getIn('S'), node.getIn('T')))
class NPZeroesLike(SimSchema):
'''Constructs a zero-filled ndarray with the same shape and data type as I.'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPZRL', [
Connector('I', np.ndarray),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', np.zeros_like(node.getIn('I')))
class NPOnes(SimSchema):
'''Constructs a one-filled ndarray with shape S and data type T.'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPONS', [
Connector('S', list),
Connector('T', str),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', np.ones(node.getIn('S'), node.getIn('T')))
class NPOnesLike(SimSchema):
'''Constructs a one-filled ndarray with the same shape and data type as I.'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPONL', [
Connector('I', np.ndarray),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', np.ones_like(node.getIn('I')))
class NPAdd(SimSchema):
'''Adds ndarrays. The result is generally an element-wise addition, with broadcasting to resolve unused dimensions. (See the numpy documentation for details.)'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPADD', [
Connector('I', np.ndarray, False),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', functools.reduce(operator.add, node.getIns('I')))
class NPMultiply(SimSchema):
'''Multiplies ndarrays. The result is generally an element-wise multiplication, with broadcasting to resolve unused dimensions. (See the numpy documentation for details.)'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPMUL', [
Connector('I', np.ndarray, False),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', functools.reduce(operator.mul, node.getIns('I')))
class NPElementAdd(SimSchema):
'''Adds the sum of ndarrays with a constant, which will be broadcast over all dimensions. (See NPAdd.)'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPEADD', [
Connector('A', np.ndarray),
Connector('B', None, False),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', node.getIn('A') + functools.reduce(operator.add, node.getIns('B')))
class NPElementMultiply(SimSchema):
'''Multiplies the product of ndarrays with a constant, which will be broadcast over all dimensions. (See NPMultiply.)'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPEMUL', [
Connector('A', np.ndarray),
Connector('B', None, False),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', node.getIn('A') * functools.reduce(operator.mul, node.getIns('B')))
class NPElementMinimum(SimSchema):
'''Returns an ndarray where each element is the minimum of the input arrays, with smaller shapes broadcast over larger shapes. (See numpy documentation for details.)'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPEMIN', [
Connector('A', np.ndarray),
Connector('B', np.ndarray),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', np.minimum(node.getIn('A'), node.getIn('B')))
class NPElementMaximum(SimSchema):
'''Returns an ndarray where each element is the maximum of the input arrays, with smaller shapes broadcast over larger shapes. (See numpy documentation for details.)'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPEMAX', [
Connector('A', np.ndarray),
Connector('B', np.ndarray),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', np.maximum(node.getIn('A'), node.getIn('B')))
class NPElementSine(SimSchema):
'''Computes an ndarray for which Q[x] = sin(I[x]) for all possible vectors x.'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPESIN', [
Connector('I', np.ndarray),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', np.sin(node.getIn('I')))
class NPElementCosine(SimSchema):
'''Computes an ndarray for which Q[x] = cos(I[x]) for all possible vectors x.'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPECOS', [
Connector('I', np.ndarray),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', np.cos(node.getIn('I')))
class NPElementTangent(SimSchema):
'''Computes an ndarray for which Q[x] = tan(I[x]) for all possible vectors x.'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPETAN', [
Connector('I', np.ndarray),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', np.tan(node.getIn('I')))
class NPElementSinc(SimSchema):
'''Computes an ndarray for which Q[x] = sinc(I[x]) for all possible vectors x.'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPESINC', [
Connector('I', np.ndarray),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', np.sinc(node.getIn('I')))
class NPLinSpace(SimSchema):
'''Computes a linear space--a unidimensional, real ndarray beginning with B inclusive and ending at E (inclusive if I, otherwise exclusive) with data type T; the ndarray will always have shape (N,) (or, rather, N elements).'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPLINS', [
Connector('B', float),
Connector('E', float),
Connector('N', int),
Connector('T', str),
Connector('I', bool),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', np.linspace(node.getIn('B'), node.getIn('E'), node.getIn('N'), dtype=node.getIn('T'), endpoint=node.getIn('I')))
class NPARange(SimSchema):
'''Computes a range--a unidimensional, real ndarray beginning with B inclusive and ending at E exclusive, with the delta between subsequent elements equal to (or as approximately as possible equal to) S, with data type T. The number of elements is ideally floor((E - B) / S), but the precision of this result is limited by the implementation and data type. See NPLinSpace for an alternative with fixed dimension.'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPARNG', [
Connector('B', float),
Connector('E', float),
Connector('S', float),
Connector('T', str),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', np.arange(node.getIn('B'), node.getIn('E'), node.getIn('S'), dtype=node.getIn('T')))
class NPSum(SimSchema):
'''Computes the sum of all elements of an ndarray.'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPSUM', [
Connector('I', np.ndarray),
], [
Connector('Q', float)
])
def step(self, node):
node.setOut('Q', np.sum(node.getIn('I')))
class NPBlackman(SimSchema):
'''Computes an N-point Blackman window.'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPBKMN', [
Connector('N', int),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', np.blackman(node.getIn('N')))
class NPConvolve(SimSchema):
'''Computes the convolution of A and B, with mode M, which may be 'full' for a complete, boundary-to-boundary convolution of size |A|+|B|-1, 'same' for a half-internal convolution of size max(|A|, |B|), or 'valid' for internal convlution of size max(|A|, |B|) - min(|A|, |B|) + 1.'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPCVLV', [
Connector('A', np.ndarray),
Connector('B', np.ndarray),
Connector('M', str),
], [
Connector('Q', np.ndarray),
])
def step(self, node):
node.setOut('Q', np.convolve(node.getIn('A'), node.getIn('B'), node.getIn('M')))
class NPContinuousConvolution(SimSchema):
'''Does a continuous convolution over time of A and B: both are convolved fully, and the boundary effects from the latter end of one convolution are contributed to the boundary of the prior convolution on the next tick, giving a sliding window of convolution. For best results, both arrays should have constant size over the simulation.'''
def __init__(self):
SimSchema.__init__(self, 'NumPy', 'NPCCVL', [
Connector('A', np.ndarray),
Connector('B', np.ndarray),
], [
Connector('Q', np.ndarray),
])
def reset(self, node):
node.overflow = np.array([], dtype=np.float64)
node.prevsig = node.overflow
def step(self, node):
sig = node.getIn('A')
win = node.getIn('B')
if len(sig) and len(win):
result = np.convolve(np.concatenate((node.prevsig, sig)), win)[len(node.prevsig):]
else:
result = sig
convsz = min(len(sig), len(node.overflow))
lerpa = np.linspace(0.0, 1.0, convsz)
result[:convsz] = lerpa * result[:convsz] + (1 - lerpa) * node.overflow[:convsz]
node.overflow = result[len(sig):]
node.prevsig = sig[-convsz:]
node.setOut('Q', result[:len(sig)])