waveforms 2.1.0__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {waveforms-2.1.0 → waveforms-2.2.0}/PKG-INFO +1 -1
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms/__init__.py +4 -3
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms/_waveform.pyi +3 -2
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms/_waveform.pyx +18 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms/utils.py +14 -12
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms/version.py +1 -1
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms/waveform.py +130 -40
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms/waveform_parser.py +11 -12
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms.egg-info/PKG-INFO +1 -1
- {waveforms-2.1.0 → waveforms-2.2.0}/LICENSE +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/MANIFEST.in +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/README.md +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/pyproject.toml +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/setup.cfg +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/setup.py +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/src/waveform.h +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/tests/test_multi_drag.py +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/tests/test_waveform.py +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/tests/test_wavevstack.py +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms/WaveformLexer.py +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms/WaveformListener.py +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms/WaveformParser.py +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms/__main__.py +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms/distortion.py +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms/multy_drag.py +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms.egg-info/SOURCES.txt +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms.egg-info/dependency_links.txt +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms.egg-info/entry_points.txt +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms.egg-info/requires.txt +0 -0
- {waveforms-2.1.0 → waveforms-2.2.0}/waveforms.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,8 @@ from .multy_drag import drag_sin, drag_sinx
|
|
|
4
4
|
from .version import __version__
|
|
5
5
|
from .waveform import (D, Waveform, WaveVStack, chirp, const, cos, cosh,
|
|
6
6
|
coshPulse, cosPulse, cut, drag, exp, function, gaussian,
|
|
7
|
-
general_cosine, hanning, interp, mixing,
|
|
8
|
-
registerBaseFunc, registerDerivative,
|
|
9
|
-
sign, sin, sinc, sinh, square, step, t,
|
|
7
|
+
general_cosine, hanning, interp, mixing, mollifier, one,
|
|
8
|
+
poly, registerBaseFunc, registerDerivative,
|
|
9
|
+
samplingPoints, sign, sin, sinc, sinh, square, step, t,
|
|
10
|
+
zero)
|
|
10
11
|
from .waveform_parser import wave_eval
|
|
@@ -28,7 +28,7 @@ def is_const(x: tuple[tuple, tuple]) -> bool:
|
|
|
28
28
|
pass
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
def basic_wave(Type, *args, shift=0) -> tuple[tuple, tuple]:
|
|
31
|
+
def basic_wave(Type: int, *args, shift: float = 0) -> tuple[tuple, tuple]:
|
|
32
32
|
pass
|
|
33
33
|
|
|
34
34
|
|
|
@@ -53,7 +53,7 @@ def calc_parts(bounds: tuple,
|
|
|
53
53
|
x: np.ndarray,
|
|
54
54
|
function_lib: dict,
|
|
55
55
|
min=-inf,
|
|
56
|
-
max=inf) -> tuple[list[np.ndarray], type]:
|
|
56
|
+
max=inf) -> tuple[list[tuple[int, int, np.ndarray]], type]:
|
|
57
57
|
pass
|
|
58
58
|
|
|
59
59
|
|
|
@@ -103,6 +103,7 @@ HYPERBOLICCHIRP: int = ...
|
|
|
103
103
|
COSH: int = ...
|
|
104
104
|
SINH: int = ...
|
|
105
105
|
DRAG: int = ...
|
|
106
|
+
MOLLIFIER: int = ...
|
|
106
107
|
|
|
107
108
|
|
|
108
109
|
def simplify(expr: tuple[tuple, tuple], eps: float) -> tuple[tuple, tuple]:
|
|
@@ -351,6 +351,18 @@ def _drag(t: np.ndarray, t0: float, freq: float, width: float, delta: float,
|
|
|
351
351
|
return Omega_x * np.cos(wt) + Omega_y * np.sin(wt)
|
|
352
352
|
|
|
353
353
|
|
|
354
|
+
def _mollifier(t: np.ndarray, r: float, d: int):
|
|
355
|
+
x = t / r
|
|
356
|
+
if d == 0:
|
|
357
|
+
return np.exp(1 / (np.abs(x)**2 - 1) + 1)
|
|
358
|
+
else:
|
|
359
|
+
p = np.poly1d([-2, 0])
|
|
360
|
+
for n in range(1, d):
|
|
361
|
+
p = np.poly1d([1, 0, -2, 0, 1]) * p.deriv() + np.poly1d(
|
|
362
|
+
[-4 * n, 0, 4 * n - 2, 0]) * p
|
|
363
|
+
return np.exp(1 / (np.abs(x)**2 - 1) + 1) * p(x) / (1 - x**2)**(2 * d) / r**d
|
|
364
|
+
|
|
365
|
+
|
|
354
366
|
LINEAR = registerBaseFunc(_LINEAR)
|
|
355
367
|
GAUSSIAN = registerBaseFunc(_GAUSSIAN)
|
|
356
368
|
ERF = registerBaseFunc(_ERF)
|
|
@@ -364,6 +376,7 @@ HYPERBOLICCHIRP = registerBaseFunc(_HYPERBOLICCHIRP)
|
|
|
364
376
|
COSH = registerBaseFunc(_COSH)
|
|
365
377
|
SINH = registerBaseFunc(_SINH)
|
|
366
378
|
DRAG = registerBaseFunc(_drag)
|
|
379
|
+
MOLLIFIER = registerBaseFunc(_mollifier)
|
|
367
380
|
|
|
368
381
|
|
|
369
382
|
def _d_LINEAR(shift, *args):
|
|
@@ -433,6 +446,10 @@ def _d_HYPERBOLICCHIRP(shift, f0, k, phi0):
|
|
|
433
446
|
shift)), (-1, 1)), ), (2 * pi * f0, ))
|
|
434
447
|
|
|
435
448
|
|
|
449
|
+
def _d_MOLLIFIER(shift, r, d):
|
|
450
|
+
return (((((MOLLIFIER, r, d+1, shift), ), (1, )), ), (1, ))
|
|
451
|
+
|
|
452
|
+
|
|
436
453
|
# register derivative
|
|
437
454
|
registerDerivative(LINEAR, _d_LINEAR)
|
|
438
455
|
registerDerivative(GAUSSIAN, _d_GAUSSIAN)
|
|
@@ -446,6 +463,7 @@ registerDerivative(SINH, _d_SINH)
|
|
|
446
463
|
registerDerivative(LINEARCHIRP, _d_LINEARCHIRP)
|
|
447
464
|
registerDerivative(EXPONENTIALCHIRP, _d_EXPONENTIALCHIRP)
|
|
448
465
|
registerDerivative(HYPERBOLICCHIRP, _d_HYPERBOLICCHIRP)
|
|
466
|
+
registerDerivative(MOLLIFIER, _d_MOLLIFIER)
|
|
449
467
|
|
|
450
468
|
|
|
451
469
|
def _cos_power_n(x, n):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from itertools import repeat
|
|
2
2
|
from types import MappingProxyType
|
|
3
|
-
from typing import Optional, Sequence
|
|
3
|
+
from typing import Optional, Sequence, cast
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
import scipy.sparse as sp
|
|
@@ -20,13 +20,13 @@ def freeze(x):
|
|
|
20
20
|
elif isinstance(x, (np.ndarray, np.matrix)):
|
|
21
21
|
x.flags.writeable = False
|
|
22
22
|
elif isinstance(x, sp.spmatrix):
|
|
23
|
-
x
|
|
24
|
-
if x
|
|
25
|
-
x
|
|
26
|
-
x
|
|
27
|
-
elif x
|
|
28
|
-
x
|
|
29
|
-
x
|
|
23
|
+
cast(np.ndarray, getattr(x, 'data')).flags.writeable = False
|
|
24
|
+
if getattr(x, 'format') in {'csr', 'csc', 'bsr'}:
|
|
25
|
+
cast(np.ndarray, getattr(x, 'indices')).flags.writeable = False
|
|
26
|
+
cast(np.ndarray, getattr(x, 'indptr')).flags.writeable = False
|
|
27
|
+
elif getattr(x, 'format') == 'coo':
|
|
28
|
+
cast(np.ndarray, getattr(x, 'row')).flags.writeable = False
|
|
29
|
+
cast(np.ndarray, getattr(x, 'col')).flags.writeable = False
|
|
30
30
|
elif isinstance(x, bytearray):
|
|
31
31
|
x = bytes(x)
|
|
32
32
|
return x
|
|
@@ -72,12 +72,14 @@ def getFTMatrix(fList: Sequence[float],
|
|
|
72
72
|
if weight is None or len(weight) == 0:
|
|
73
73
|
weight = np.full(numOfPoints, 2 / numOfPoints)
|
|
74
74
|
if phaseList is None or len(phaseList) == 0:
|
|
75
|
-
|
|
75
|
+
phase_list = np.zeros_like(fList)
|
|
76
|
+
else:
|
|
77
|
+
phase_list = phaseList
|
|
76
78
|
if weight.ndim == 1:
|
|
77
|
-
|
|
79
|
+
weight_list = repeat(weight)
|
|
78
80
|
else:
|
|
79
|
-
|
|
80
|
-
for f, phase, weight in zip(fList,
|
|
81
|
+
weight_list = weight
|
|
82
|
+
for f, phase, weight in zip(fList, phase_list, weight_list):
|
|
81
83
|
e.append(weight * np.exp(-1j * (2 * np.pi * f * t + phase)))
|
|
82
84
|
return np.asarray(e).T
|
|
83
85
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""Define version number here and read it from setup.py automatically"""
|
|
2
|
-
__version__ = "2.
|
|
2
|
+
__version__ = "2.2.0"
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
from fractions import Fraction
|
|
2
|
+
from typing import Generator, Iterable, cast
|
|
2
3
|
|
|
3
4
|
import numpy as np
|
|
4
5
|
from numpy import e, inf, pi
|
|
6
|
+
from numpy.typing import NDArray
|
|
5
7
|
from scipy.signal import sosfilt
|
|
6
8
|
|
|
7
|
-
from ._waveform import (
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
registerDerivative, shift, simplify, wave_sum)
|
|
9
|
+
from ._waveform import (
|
|
10
|
+
_D, COS, COSH, DRAG, ERF, EXP, EXPONENTIALCHIRP, GAUSSIAN, HYPERBOLICCHIRP,
|
|
11
|
+
INTERP, LINEAR, LINEARCHIRP, MOLLIFIER, NDIGITS, SINC, SINH, _baseFunc,
|
|
12
|
+
_baseFunc_latex, _const, _half, _one, _zero, add, basic_wave, calc_parts,
|
|
13
|
+
filter, is_const, merge_waveform, mul, pow, registerBaseFunc,
|
|
14
|
+
registerBaseFuncLatex, registerDerivative, shift, simplify, wave_sum)
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
def _test_spec_num(num, spec):
|
|
@@ -124,7 +125,7 @@ class Waveform:
|
|
|
124
125
|
self.start = None
|
|
125
126
|
self.stop = None
|
|
126
127
|
self.sample_rate = None
|
|
127
|
-
self.filters = None
|
|
128
|
+
self.filters: tuple[np.ndarray, float] | None = None
|
|
128
129
|
self.label = None
|
|
129
130
|
|
|
130
131
|
@staticmethod
|
|
@@ -160,12 +161,14 @@ class Waveform:
|
|
|
160
161
|
else:
|
|
161
162
|
return min(self.stop, self._end(self.bounds, self.seq))
|
|
162
163
|
|
|
163
|
-
def sample(
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
164
|
+
def sample(
|
|
165
|
+
self,
|
|
166
|
+
sample_rate=None,
|
|
167
|
+
out: np.ndarray | None = None,
|
|
168
|
+
chunk_size=None,
|
|
169
|
+
function_lib=None,
|
|
170
|
+
filters: tuple[np.ndarray, float] | None = None
|
|
171
|
+
) -> np.ndarray | Iterable[np.ndarray]:
|
|
169
172
|
if sample_rate is None:
|
|
170
173
|
sample_rate = self.sample_rate
|
|
171
174
|
if self.start is None or self.stop is None or sample_rate is None:
|
|
@@ -179,28 +182,39 @@ class Waveform:
|
|
|
179
182
|
sig = self.__call__(x, out=out, function_lib=function_lib)
|
|
180
183
|
if filters is not None:
|
|
181
184
|
sos, initial = filters
|
|
185
|
+
if not isinstance(sos, np.ndarray):
|
|
186
|
+
sos = np.array(sos)
|
|
187
|
+
elif not sos.flags.writeable:
|
|
188
|
+
sos = sos.copy()
|
|
182
189
|
if initial:
|
|
183
|
-
sig = sosfilt(sos,
|
|
190
|
+
sig = cast(np.ndarray, sosfilt(sos,
|
|
191
|
+
sig - initial)) + initial
|
|
184
192
|
else:
|
|
185
|
-
sig = sosfilt(sos, sig)
|
|
186
|
-
return sig
|
|
193
|
+
sig = cast(np.ndarray, sosfilt(sos, sig))
|
|
194
|
+
return cast(np.ndarray, sig)
|
|
187
195
|
else:
|
|
188
196
|
return self._sample_iter(sample_rate, chunk_size, out,
|
|
189
197
|
function_lib, filters)
|
|
190
198
|
|
|
191
|
-
def _sample_iter(
|
|
192
|
-
|
|
193
|
-
|
|
199
|
+
def _sample_iter(
|
|
200
|
+
self, sample_rate, chunk_size, out: np.ndarray | None, function_lib,
|
|
201
|
+
filters: tuple[np.ndarray, float] | None
|
|
202
|
+
) -> Generator[np.ndarray, None, None]:
|
|
203
|
+
start = cast(float, self.start)
|
|
194
204
|
start_n = 0
|
|
195
205
|
if filters is not None:
|
|
196
206
|
sos, initial = filters
|
|
207
|
+
if not isinstance(sos, np.ndarray):
|
|
208
|
+
sos = np.array(sos)
|
|
209
|
+
elif not sos.flags.writeable:
|
|
210
|
+
sos = sos.copy()
|
|
197
211
|
# zi = sosfilt_zi(sos)
|
|
198
212
|
zi = np.zeros((sos.shape[0], 2))
|
|
199
213
|
length = chunk_size / sample_rate
|
|
200
|
-
while start < self.stop:
|
|
201
|
-
if start + length > self.stop:
|
|
202
|
-
length = self.stop - start
|
|
203
|
-
stop = self.stop
|
|
214
|
+
while start < cast(float, self.stop):
|
|
215
|
+
if start + length > cast(float, self.stop):
|
|
216
|
+
length = cast(float, self.stop) - start
|
|
217
|
+
stop = cast(float, self.stop)
|
|
204
218
|
size = round((stop - start) * sample_rate)
|
|
205
219
|
else:
|
|
206
220
|
stop = start + length
|
|
@@ -209,13 +223,17 @@ class Waveform:
|
|
|
209
223
|
|
|
210
224
|
if filters is None:
|
|
211
225
|
if out is not None:
|
|
212
|
-
yield
|
|
213
|
-
|
|
214
|
-
|
|
226
|
+
yield cast(
|
|
227
|
+
np.ndarray,
|
|
228
|
+
self.__call__(x,
|
|
229
|
+
out=out[start_n:],
|
|
230
|
+
function_lib=function_lib))
|
|
215
231
|
else:
|
|
216
|
-
yield
|
|
232
|
+
yield cast(np.ndarray,
|
|
233
|
+
self.__call__(x, function_lib=function_lib))
|
|
217
234
|
else:
|
|
218
|
-
sig =
|
|
235
|
+
sig = cast(np.ndarray,
|
|
236
|
+
self.__call__(x, function_lib=function_lib))
|
|
219
237
|
if initial:
|
|
220
238
|
sig -= initial
|
|
221
239
|
sig, zi = sosfilt(sos, sig, zi=zi)
|
|
@@ -223,7 +241,7 @@ class Waveform:
|
|
|
223
241
|
sig += initial
|
|
224
242
|
if out is not None:
|
|
225
243
|
out[start_n:start_n + size] = sig
|
|
226
|
-
yield sig
|
|
244
|
+
yield cast(np.ndarray, sig)
|
|
227
245
|
|
|
228
246
|
start = stop
|
|
229
247
|
start_n += chunk_size
|
|
@@ -498,16 +516,21 @@ class Waveform:
|
|
|
498
516
|
for start, stop, part in parts:
|
|
499
517
|
out[start:stop] += part
|
|
500
518
|
|
|
501
|
-
def __call__(
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
519
|
+
def __call__(
|
|
520
|
+
self,
|
|
521
|
+
x,
|
|
522
|
+
frag=False,
|
|
523
|
+
out: np.ndarray | None = None,
|
|
524
|
+
accumulate=False,
|
|
525
|
+
function_lib=None
|
|
526
|
+
) -> NDArray[np.float64] | list[tuple[int, int,
|
|
527
|
+
NDArray[np.float64]]] | np.float64:
|
|
507
528
|
if function_lib is None:
|
|
508
529
|
function_lib = _baseFunc
|
|
509
530
|
if isinstance(x, (int, float, complex)):
|
|
510
|
-
return
|
|
531
|
+
return cast(
|
|
532
|
+
NDArray[np.float64],
|
|
533
|
+
self.__call__(np.array([x]), function_lib=function_lib))[0]
|
|
511
534
|
parts, dtype = calc_parts(self.bounds, self.seq, x, function_lib,
|
|
512
535
|
self.min, self.max)
|
|
513
536
|
if not frag:
|
|
@@ -957,6 +980,25 @@ def _format_DRAG(shift, *args):
|
|
|
957
980
|
return f"DRAG(...)"
|
|
958
981
|
|
|
959
982
|
|
|
983
|
+
def _format_MOLLIFIER(shift, *args):
|
|
984
|
+
r = _num_latex(args[0])
|
|
985
|
+
d = _num_latex(args[1])
|
|
986
|
+
shift_str = _num_latex(-shift)
|
|
987
|
+
if shift_str == '0':
|
|
988
|
+
shift_str = ''
|
|
989
|
+
elif shift_str[0] != '-':
|
|
990
|
+
shift_str = '+' + shift_str
|
|
991
|
+
|
|
992
|
+
if d == '0':
|
|
993
|
+
return f"\\mathrm{{Mollifier}}\\left(t{shift_str}, r={r}\\right)"
|
|
994
|
+
elif d == '1':
|
|
995
|
+
return f"\\mathrm{{Mollifier}}'\\left(t{shift_str}, r={r}\\right)"
|
|
996
|
+
elif d == '2':
|
|
997
|
+
return f"\\mathrm{{Mollifier}}''\\left(t{shift_str}, r={r}\\right)"
|
|
998
|
+
else:
|
|
999
|
+
return f"\\mathrm{{Mollifier}}^{{({d})}}\\left(t{shift_str}, r={r}\\right)"
|
|
1000
|
+
|
|
1001
|
+
|
|
960
1002
|
registerBaseFuncLatex(LINEAR, _format_LINEAR)
|
|
961
1003
|
registerBaseFuncLatex(GAUSSIAN, _format_GAUSSIAN)
|
|
962
1004
|
registerBaseFuncLatex(ERF, _format_ERF)
|
|
@@ -966,12 +1008,26 @@ registerBaseFuncLatex(EXP, _format_EXP)
|
|
|
966
1008
|
registerBaseFuncLatex(COSH, _format_COSH)
|
|
967
1009
|
registerBaseFuncLatex(SINH, _format_SINH)
|
|
968
1010
|
registerBaseFuncLatex(DRAG, _format_DRAG)
|
|
1011
|
+
registerBaseFuncLatex(MOLLIFIER, _format_MOLLIFIER)
|
|
969
1012
|
|
|
970
1013
|
|
|
971
|
-
def D(wav):
|
|
1014
|
+
def D(wav: Waveform, d: int = 1) -> Waveform:
|
|
972
1015
|
"""derivative
|
|
1016
|
+
|
|
1017
|
+
Parameters
|
|
1018
|
+
----------
|
|
1019
|
+
wav : Waveform
|
|
1020
|
+
The waveform to take the derivative of.
|
|
1021
|
+
d : int, optional
|
|
1022
|
+
The order of the derivative, by default 1.
|
|
973
1023
|
"""
|
|
974
|
-
|
|
1024
|
+
assert d >= 0 and isinstance(d, int), "d must be a non-negative integer"
|
|
1025
|
+
if d == 0:
|
|
1026
|
+
return wav
|
|
1027
|
+
elif d == 1:
|
|
1028
|
+
return Waveform(bounds=wav.bounds, seq=tuple(_D(x) for x in wav.seq))
|
|
1029
|
+
else:
|
|
1030
|
+
return D(D(wav, d - 1), 1)
|
|
975
1031
|
|
|
976
1032
|
|
|
977
1033
|
def convolve(a, b):
|
|
@@ -1181,6 +1237,40 @@ def slepian(duration, *arg):
|
|
|
1181
1237
|
return wav * square(duration)
|
|
1182
1238
|
|
|
1183
1239
|
|
|
1240
|
+
def mollifier(width, plateau: float = 0.0, d: int = 0):
|
|
1241
|
+
"""
|
|
1242
|
+
Mollifier function is a smooth function that is 1 at the origin and 0 outside a certain radius.
|
|
1243
|
+
It is defined as:
|
|
1244
|
+
|
|
1245
|
+
f(x) = exp(1 / ((x / r) ^ 2 - 1) + 1) in case |x| < r
|
|
1246
|
+
= 0 in case |x| >= r
|
|
1247
|
+
where r = width / 2 is the radius of the mollifier.
|
|
1248
|
+
|
|
1249
|
+
The parameter plateau is the width of the plateau.
|
|
1250
|
+
The parameter d is the order of the derivative.
|
|
1251
|
+
"""
|
|
1252
|
+
assert d >= 0 and isinstance(d, int), "d must be a non-negative integer"
|
|
1253
|
+
assert width > 0, "width must be positive"
|
|
1254
|
+
|
|
1255
|
+
if plateau <= 0:
|
|
1256
|
+
return Waveform(bounds=(-0.5 * width, 0.5 * width, inf),
|
|
1257
|
+
seq=(_zero, basic_wave(MOLLIFIER, width / 2,
|
|
1258
|
+
d), _zero))
|
|
1259
|
+
else:
|
|
1260
|
+
return Waveform(bounds=(-0.5 * width - 0.5 * plateau, -0.5 * plateau,
|
|
1261
|
+
0.5 * plateau, 0.5 * width + 0.5 * plateau,
|
|
1262
|
+
inf),
|
|
1263
|
+
seq=(_zero,
|
|
1264
|
+
basic_wave(MOLLIFIER,
|
|
1265
|
+
width / 2,
|
|
1266
|
+
d,
|
|
1267
|
+
shift=-0.5 * plateau), _one,
|
|
1268
|
+
basic_wave(MOLLIFIER,
|
|
1269
|
+
width / 2,
|
|
1270
|
+
d,
|
|
1271
|
+
shift=0.5 * plateau), _zero))
|
|
1272
|
+
|
|
1273
|
+
|
|
1184
1274
|
def _poly(*a):
|
|
1185
1275
|
"""
|
|
1186
1276
|
a[0] + a[1] * t + a[2] * t**2 + ...
|
|
@@ -1376,7 +1466,7 @@ def mixing(I,
|
|
|
1376
1466
|
__all__ = [
|
|
1377
1467
|
'D', 'Waveform', 'chirp', 'const', 'cos', 'cosh', 'coshPulse', 'cosPulse',
|
|
1378
1468
|
'cut', 'drag', 'exp', 'function', 'gaussian', 'general_cosine', 'hanning',
|
|
1379
|
-
'interp', 'mixing', 'one', 'poly', 'registerBaseFunc',
|
|
1469
|
+
'interp', 'mixing', 'mollifier', 'one', 'poly', 'registerBaseFunc',
|
|
1380
1470
|
'registerDerivative', 'samplingPoints', 'sign', 'sin', 'sinc', 'sinh',
|
|
1381
1471
|
'square', 'step', 't', 'zero'
|
|
1382
1472
|
]
|
|
@@ -30,9 +30,9 @@ class WaveformVisitor:
|
|
|
30
30
|
self.functions = [
|
|
31
31
|
'D', 'chirp', 'const', 'cos', 'cosh', 'coshPulse', 'cosPulse',
|
|
32
32
|
'cut', 'drag', 'drag_sin', 'drag_sinx', 'exp', 'gaussian',
|
|
33
|
-
'general_cosine', 'hanning', 'interp', 'mixing', '
|
|
34
|
-
'
|
|
35
|
-
't', 'zero'
|
|
33
|
+
'general_cosine', 'hanning', 'interp', 'mixing', 'mollifier',
|
|
34
|
+
'one', 'poly', 'samplingPoints', 'sign', 'sin', 'sinc', 'sinh',
|
|
35
|
+
'square', 'step', 't', 'zero'
|
|
36
36
|
]
|
|
37
37
|
self.constants = {
|
|
38
38
|
'pi': waveform.pi,
|
|
@@ -226,14 +226,13 @@ def _generate_antlr_parser():
|
|
|
226
226
|
|
|
227
227
|
# Generate ANTLR files
|
|
228
228
|
try:
|
|
229
|
-
result = subprocess.run(
|
|
230
|
-
"antlr4", "-Dlanguage=Python3",
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
check=True)
|
|
229
|
+
result = subprocess.run(
|
|
230
|
+
["antlr4", "-Dlanguage=Python3",
|
|
231
|
+
str(grammar_file)],
|
|
232
|
+
cwd=str(current_dir),
|
|
233
|
+
capture_output=True,
|
|
234
|
+
text=True,
|
|
235
|
+
check=True)
|
|
237
236
|
except (subprocess.CalledProcessError, FileNotFoundError) as e:
|
|
238
237
|
# Fall back to java command if antlr4 command is not available
|
|
239
238
|
try:
|
|
@@ -258,7 +257,7 @@ def parse_waveform_expression(expr: str) -> waveform.Waveform:
|
|
|
258
257
|
try:
|
|
259
258
|
# Generate parser files if they don't exist
|
|
260
259
|
# _generate_antlr_parser()
|
|
261
|
-
|
|
260
|
+
|
|
262
261
|
# Import generated ANTLR classes
|
|
263
262
|
from .WaveformLexer import WaveformLexer
|
|
264
263
|
from .WaveformParser import WaveformParser
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|