From a54b39001f71b9dfe372a5f00ca10ae742046888 Mon Sep 17 00:00:00 2001 From: Ian Guinn Date: Sun, 28 Apr 2024 17:28:34 -0400 Subject: [PATCH 1/4] bi_level_zero_crossing_time_points now outputs the number of crossings found. If number of crossings is larger than output array length, stop trying to fill output array --- src/dspeed/processors/time_point_thresh.py | 27 ++++++++------ tests/processors/test_time_point_thresh.py | 43 ++++++++++++++-------- 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/src/dspeed/processors/time_point_thresh.py b/src/dspeed/processors/time_point_thresh.py index 12c8449..6762638 100644 --- a/src/dspeed/processors/time_point_thresh.py +++ b/src/dspeed/processors/time_point_thresh.py @@ -371,10 +371,10 @@ def multi_time_point_thresh( @guvectorize( [ - "void(float32[:], float32, float32, float32, float32, float32[:], float32[:])", - "void(float64[:], float64, float64, float64, float64, float64[:], float64[:])", + "void(float32[:], float32, float32, float32, float32, uint32[:], float32[:], float32[:])", + "void(float64[:], float64, float64, float64, float64, uint32[:], float64[:], float64[:])", ], - "(n),(),(),(),(),(m),(m)", + "(n),(),(),(),(),(),(m),(m)", **nb_kwargs, ) def bi_level_zero_crossing_time_points( @@ -383,6 +383,7 @@ def bi_level_zero_crossing_time_points( a_neg_threshold_in: float, gate_time_in: int, t_start_in: int, + n_crossings_out: int, polarity_out: np.array, t_trig_times_out: np.array, ) -> None: @@ -403,6 +404,8 @@ def bi_level_zero_crossing_time_points( The number of samples that the next threshold crossing has to be within in order to count a 0 crossing t_start_in the starting index. + n_crossings_out + the number of zero-crossings found. Note: if there are more zeros than elements in output arrays, this will continue to increment but the polarity and trigger time will not be added to the output buffers polarity_out An array holding the polarity of identified pulses. 0 for negative and 1 for positive t_trig_times_out @@ -418,7 +421,7 @@ def bi_level_zero_crossing_time_points( "trig_times_out": { "function": "multi_trigger_time", "module": "dspeed.processors", - "args": ["wf_rc_cr2", "5", "-10", 0, "polarity_out(20)", "trig_times_out(20)"], + "args": ["wf_rc_cr2", "5", "-10", 0, "n_crossings", "polarity_out(20, vector_len=n_crossings)", "trig_times_out(20, vector_len=n_crossings)"], "unit": "ns" } """ @@ -449,7 +452,7 @@ def bi_level_zero_crossing_time_points( is_above_thresh = False is_below_thresh = False crossed_zero = False - trig_array_idx = 0 + n_crossings_out[0] = 0 for i in range(int(t_start_in), len(w_in) - 1, 1): if is_below_thresh and (w_in[i] <= 0 < w_in[i + 1]): crossed_zero = True @@ -459,9 +462,10 @@ def bi_level_zero_crossing_time_points( if w_in[i] <= a_pos_threshold_in < w_in[i + 1]: if crossed_zero and is_below_thresh: if i - is_below_thresh < gate_time_in: - t_trig_times_out[trig_array_idx] = neg_trig_time_candidate - polarity_out[trig_array_idx] = 0 - trig_array_idx += 1 + if n_crossings_out[0] < len(polarity_out): + t_trig_times_out[n_crossings_out[0]] = neg_trig_time_candidate + polarity_out[n_crossings_out[0]] = 0 + n_crossings_out[0] += 1 else: is_above_thresh = i @@ -478,9 +482,10 @@ def bi_level_zero_crossing_time_points( if w_in[i] >= a_neg_threshold_in > w_in[i + 1]: if crossed_zero and is_above_thresh: if i - is_above_thresh < gate_time_in: - t_trig_times_out[trig_array_idx] = pos_trig_time_candidate - polarity_out[trig_array_idx] = 1 - trig_array_idx += 1 + if n_crossings_out[0] < len(polarity_out): + t_trig_times_out[n_crossings_out[0]] = pos_trig_time_candidate + polarity_out[n_crossings_out[0]] = 1 + n_crossings_out[0] += 1 else: is_below_thresh = i is_above_thresh = False diff --git a/tests/processors/test_time_point_thresh.py b/tests/processors/test_time_point_thresh.py index ee18907..5e4be9d 100644 --- a/tests/processors/test_time_point_thresh.py +++ b/tests/processors/test_time_point_thresh.py @@ -194,37 +194,38 @@ def test_bi_level_zero_crossing_time_points(compare_numba_vs_python): # ensure that if there is a nan in w_in, all nans are outputted w_in = np.ones(100) w_in[4] = np.nan + n_out = np.zeros(1, 'uint32') t_out = np.zeros(5) pol_out = np.zeros(5) - bi_level_zero_crossing_time_points(w_in, 100, 100, 100, 0, pol_out, t_out) + bi_level_zero_crossing_time_points(w_in, 100, 100, 100, 0, n_out, pol_out, t_out) assert np.isnan(t_out).all() # ensure the ValueError is raised if the polarity output array is different length than the time point output array t_start_in = 1.02 with pytest.raises(ValueError): bi_level_zero_crossing_time_points( - np.ones(9), 100, 100, 100, t_start_in, pol_out, np.zeros(1) + np.ones(9), 100, 100, 100, t_start_in, n_out, pol_out, np.zeros(1) ) # ensure the DSPFatal is raised if initial timepoint is not an integer t_start_in = 1.02 with pytest.raises(DSPFatal): bi_level_zero_crossing_time_points( - np.ones(9), 100, 100, 100, t_start_in, pol_out, t_out + np.ones(9), 100, 100, 100, t_start_in, n_out, pol_out, t_out ) # ensure the DSPFatal is raised if initial timepoint is not negative t_start_in = -2 with pytest.raises(DSPFatal): bi_level_zero_crossing_time_points( - np.ones(9), 100, 100, 100, t_start_in, pol_out, t_out + np.ones(9), 100, 100, 100, t_start_in, n_out, pol_out, t_out ) # ensure the DSPFatal is raised if initial timepoint is outside length of waveform t_start_in = 100 with pytest.raises(DSPFatal): bi_level_zero_crossing_time_points( - np.ones(9), 100, 100, 100, t_start_in, pol_out, t_out + np.ones(9), 100, 100, 100, t_start_in, n_out, pol_out, t_out ) early_trig = 500 # start pulse1 500 samples from the start of the wf @@ -260,7 +261,7 @@ def test_bi_level_zero_crossing_time_points(compare_numba_vs_python): t_trig_times_out = np.zeros(5) pol_out = np.zeros(5) bi_level_zero_crossing_time_points( - pulse, 2000, -2000, gate_time, 0, pol_out, t_trig_times_out + pulse, 2000, -2000, gate_time, 0, n_out, pol_out, t_trig_times_out ) cross_1 = early_trig + 2 * tau - 1 # minus 1 from delay? @@ -276,7 +277,7 @@ def test_bi_level_zero_crossing_time_points(compare_numba_vs_python): t_trig_times_out = np.zeros(5) pol_out = np.zeros(5) bi_level_zero_crossing_time_points( - -1 * pulse, 2000, -2000, gate_time, 0, pol_out, t_trig_times_out + -1 * pulse, 2000, -2000, gate_time, 0, n_out, pol_out, t_trig_times_out ) assert np.allclose(int(t_trig_times_out[0]), cross_1, rtol=1) assert np.allclose(int(t_trig_times_out[1]), cross_2, rtol=1) @@ -287,7 +288,7 @@ def test_bi_level_zero_crossing_time_points(compare_numba_vs_python): t_trig_times_out = np.zeros(5) pol_out = np.zeros(5) bi_level_zero_crossing_time_points( - pulse, 2000, -300000, gate_time, 0, pol_out, t_trig_times_out + pulse, 2000, -300000, gate_time, 0, n_out, pol_out, t_trig_times_out ) assert np.isnan(t_trig_times_out).all() assert np.isnan(pol_out).all() @@ -296,7 +297,7 @@ def test_bi_level_zero_crossing_time_points(compare_numba_vs_python): t_trig_times_out = np.zeros(5) pol_out = np.zeros(5) bi_level_zero_crossing_time_points( - -1 * pulse, 300000, -2000, gate_time, 0, pol_out, t_trig_times_out + -1 * pulse, 300000, -2000, gate_time, 0, n_out, pol_out, t_trig_times_out ) assert np.isnan(t_trig_times_out).all() assert np.isnan(pol_out).all() @@ -305,7 +306,7 @@ def test_bi_level_zero_crossing_time_points(compare_numba_vs_python): t_trig_times_out = np.zeros(5) pol_out = np.zeros(5) bi_level_zero_crossing_time_points( - pulse, 300000, 300000, gate_time, 0, pol_out, t_trig_times_out + pulse, 300000, 300000, gate_time, 0, n_out, pol_out, t_trig_times_out ) assert np.isnan(t_trig_times_out).all() assert np.isnan(pol_out).all() @@ -314,7 +315,7 @@ def test_bi_level_zero_crossing_time_points(compare_numba_vs_python): t_trig_times_out = np.zeros(5) pol_out = np.zeros(5) bi_level_zero_crossing_time_points( - np.linspace(-1, 100, 101), 4, -4, gate_time, 0, pol_out, t_trig_times_out + np.linspace(-1, 100, 101), 4, -4, gate_time, 0, n_out, pol_out, t_trig_times_out ) assert np.isnan(t_trig_times_out).all() assert np.isnan(pol_out).all() @@ -323,7 +324,7 @@ def test_bi_level_zero_crossing_time_points(compare_numba_vs_python): t_trig_times_out = np.zeros(5) pol_out = np.zeros(5) bi_level_zero_crossing_time_points( - -1 * np.linspace(-1, 100, 101), 4, -4, gate_time, 0, pol_out, t_trig_times_out + -1 * np.linspace(-1, 100, 101), 4, -4, gate_time, 0, n_out, pol_out, t_trig_times_out ) assert np.isnan(t_trig_times_out).all() assert np.isnan(pol_out).all() @@ -334,7 +335,7 @@ def test_bi_level_zero_crossing_time_points(compare_numba_vs_python): t_trig_times_out = np.zeros(5) pol_out = np.zeros(5) bi_level_zero_crossing_time_points( - pulse * scale_arr, 2000, -20000, gate_time, 0, pol_out, t_trig_times_out + pulse * scale_arr, 2000, -20000, gate_time, 0, n_out, pol_out, t_trig_times_out ) assert np.allclose( int(t_trig_times_out[0]), cross_2, rtol=1 @@ -347,7 +348,7 @@ def test_bi_level_zero_crossing_time_points(compare_numba_vs_python): t_trig_times_out = np.zeros(5) pol_out = np.zeros(5) bi_level_zero_crossing_time_points( - pulse * scale_arr, 2000, -20000, gate_time, 0, pol_out, t_trig_times_out + pulse * scale_arr, 2000, -20000, gate_time, 0, n_out, pol_out, t_trig_times_out ) assert np.allclose( int(t_trig_times_out[0]), cross_1, rtol=1 @@ -360,9 +361,21 @@ def test_bi_level_zero_crossing_time_points(compare_numba_vs_python): t_trig_times_out = np.zeros(5) pol_out = np.zeros(5) bi_level_zero_crossing_time_points( - pulse * scale_arr, 50000, -2000, gate_time, 0, pol_out, t_trig_times_out + pulse * scale_arr, 50000, -2000, gate_time, 0, n_out, pol_out, t_trig_times_out ) assert np.allclose( int(t_trig_times_out[0]), cross_2, rtol=1 ) # only the 2nd time point should have been crossed assert int(pol_out[0]) == 1 + + # Check for overflow. This should not fail and should return n_crossings greater than the length of the outputs + w_in = np.zeros(100, 'float')*10 + w_in[::2] = -10 + w_in[1::2] = 10 + pol_out = np.zeros(30) + t_trig_out = np.zeros(30) + bi_level_zero_crossing_time_points( + w_in, 1, 1, 10, 0, n_out, pol_out, t_trig_out + ) + assert np.all(pol_out==0) + assert n_out[0] == 49 From 66689f91492e94fca901803a10ddd06f030fd5b7 Mon Sep 17 00:00:00 2001 From: Ian Guinn Date: Sun, 28 Apr 2024 18:05:10 -0400 Subject: [PATCH 2/4] Removed fftw processors --- setup.cfg | 1 - src/dspeed/processors/__init__.py | 4 - src/dspeed/processors/fftw.py | 280 ----------------------------- tests/configs/icpc-dsp-config.json | 18 +- tests/processors/test_fftw.py | 88 --------- 5 files changed, 2 insertions(+), 389 deletions(-) delete mode 100644 src/dspeed/processors/fftw.py delete mode 100644 tests/processors/test_fftw.py diff --git a/setup.cfg b/setup.cfg index 2ccee9f..502feca 100644 --- a/setup.cfg +++ b/setup.cfg @@ -41,7 +41,6 @@ install_requires = parse pint pyarrow - pyfftw scipy tqdm>=4.27 python_requires = >=3.9 diff --git a/src/dspeed/processors/__init__.py b/src/dspeed/processors/__init__.py index 4c0e146..02ba80d 100644 --- a/src/dspeed/processors/__init__.py +++ b/src/dspeed/processors/__init__.py @@ -63,7 +63,6 @@ from .convolutions import convolve_wf, fft_convolve_wf from .dwt import discrete_wavelet_transform from .energy_kernels import cusp_filter, dplms, zac_filter -from .fftw import dft, inv_dft, psd from .fixed_time_pickoff import fixed_time_pickoff from .gaussian_filter1d import gaussian_filter1d from .get_multi_local_extrema import get_multi_local_extrema @@ -115,9 +114,6 @@ "t0_filter", "zac_filter", "discrete_wavelet_transform", - "dft", - "inv_dft", - "psd", "fixed_time_pickoff", "gaussian_filter1d", "get_multi_local_extrema", diff --git a/src/dspeed/processors/fftw.py b/src/dspeed/processors/fftw.py deleted file mode 100644 index dc923b2..0000000 --- a/src/dspeed/processors/fftw.py +++ /dev/null @@ -1,280 +0,0 @@ -from __future__ import annotations - -from typing import Callable - -import numpy as np -from numba import guvectorize -from pyfftw import FFTW - -from ..utils import ProcChainVarBase -from ..utils import numba_defaults_kwargs as nb_kwargs - - -def dft( - w_in: np.ndarray | ProcChainVarBase, w_out: np.ndarray | ProcChainVarBase -) -> Callable: - """Perform discrete Fourier transforms using the FFTW library. - - Parameters - ---------- - w_in - the input waveform. - w_out - the output fourier transform. - - JSON Configuration Example - -------------------------- - - .. code-block :: json - - "wf_dft": { - "function": "dft", - "module": "dspeed.processors", - "args": ["wf", "wf_dft"], - "init_args": ["wf", "wf_dft"] - } - - Note - ---- - FFTW optimizes the FFT algorithm based on the size of the arrays, with SIMD - parallelized commands. This optimization requires initialization, so this - is a factory function that returns a Numba gufunc that performs the FFT. - FFTW works on fixed memory buffers, so you must tell it what memory to use - ahead of time. When using this with - :class:`~.dsp.processing_chain.ProcessingChain`, the output waveform's size, - dtype and coordinate grid units can be set automatically. The - possible `dtypes` for the input/outputs are: - - =============================== ========= =============================== ============= - :class:`numpy.dtype` Size :class:`numpy.dtype` Size - ------------------------------- --------- ------------------------------- ------------- - ``float32``/``float`` :math:`n` ``complex64`` :math:`n/2+1` - ``float64``/``double`` :math:`n` ``complex128`` :math:`n/2+1` - ``float128``/``longdouble`` :math:`n` ``complex256``/``clongdouble`` :math:`n/2+1` - ``complex64`` :math:`n` ``complex64`` :math:`n` - ``complex128`` :math:`n` ``complex128`` :math:`n` - ``complex256``/``clongdouble`` :math:`n` ``complex256``/``clongdouble`` :math:`n` - =============================== ========= =============================== ============= - """ - # if we have a ProcChainVar, set up the output and get numpy arrays - if isinstance(w_in, ProcChainVarBase) and isinstance(w_out, ProcChainVarBase): - c = w_in.dtype.kind - s = w_in.dtype.itemsize - if c == "f": - w_out.update_auto( - shape=w_in.shape[:-1] + (w_in.shape[-1] // 2 + 1,), - dtype=np.dtype(f"c{2*s}"), - period=1.0 / w_in.period / w_in.shape[-1], - ) - elif c == "c": - w_out.update_auto( - shape=w_in.shape, - dtype=np.dtype(f"c{s}"), - period=1.0 / w_in.period / w_in.shape[-1], - ) - w_in = w_in.buffer - w_out = w_out.buffer - - try: - dft_fun = FFTW(w_in, w_out, axes=(-1,), direction="FFTW_FORWARD") - except ValueError: - raise ValueError( - "incompatible array types/shapes. See function documentation for allowed values" - ) - - typesig = "void(" + str(w_in.dtype) + "[:, :], " + str(w_out.dtype) + "[:, :])" - sizesig = "(m, n)->(m, n)" if w_in.shape == w_out.shape else "(m, n),(m, l)" - - @guvectorize( - [typesig], - sizesig, - **nb_kwargs( - cache=False, - forceobj=True, - ), - ) - def dft(wf_in: np.ndarray, dft_out: np.ndarray) -> None: - dft_fun(wf_in, dft_out) - - return dft - - -def inv_dft(w_in: np.ndarray, w_out: np.ndarray) -> Callable: - """Perform inverse discrete Fourier transforms using the FFTW library. - - Parameters - ---------- - w_in - the input fourier transformed waveform. - w_out - the output time-domain waveform. - - JSON Configuration Example - -------------------------- - - .. code-block :: json - - "wf_invdft": { - "function": "inv_dft", - "module": "dspeed.processors", - "args": ["wf_dft", "wf_invdft"], - "init_args": ["wf_dft", "wf_invdft"] - } - - Note - ---- - FFTW optimizes the FFT algorithm based on the size of the arrays, with SIMD - parallelized commands. This optimization requires initialization, so this - is a factory function that returns a Numba gufunc that performs the FFT. - FFTW works on fixed memory buffers, so you must tell it what memory to use - ahead of time. When using this with - :class:`~.dsp.processing_chain.ProcessingChain`, the output waveform's size, - dtype and coordinate grid units can be set automatically. The automated - behavior will produce a real output by default, unless you specify a complex - output. Possible `dtypes` for the input/outputs are: - - =============================== ============= =============================== ========= - :class:`numpy.dtype` Size :class:`numpy.dtype` Size - ------------------------------- ------------- ------------------------------- --------- - ``complex64`` :math:`n/2+1` ``float32``/``float`` :math:`n` - ``complex128`` :math:`n/2+1` ``float64``/``double`` :math:`n` - ``complex256``/``clongdouble`` :math:`n/2+1` ``float128``/``longdouble`` :math:`n` - ``complex64`` :math:`n` ``complex64`` :math:`n` - ``complex128`` :math:`n` ``complex128`` :math:`n` - ``complex256``/``clongdouble`` :math:`n` ``complex256``/``clongdouble`` :math:`n` - =============================== ============= =============================== ========= - """ - # if we have a ProcChainVar, set up the output and get numpy arrays - if isinstance(w_in, ProcChainVarBase) and isinstance(w_out, ProcChainVarBase): - s = w_in.dtype.itemsize - if w_out.dtype == "auto": - w_out.update_auto( - shape=w_in.shape[:-1] + (2 * (w_in.shape[-1] - 1),), - dtype=np.dtype(f"f{s//2}"), - period=1.0 / w_in.period / w_in.shape[-1], - ) - else: - w_out.update_auto( - shape=( - w_in.shape - if w_out.dtype.kind == "c" - else w_in.shape[:-1] + (2 * (w_in.shape[-1] - 1),) - ), - period=1.0 / w_in.period / w_in.shape[-1], - ) - w_in = w_in.buffer - w_out = w_out.buffer - - try: - idft_fun = FFTW(w_in, w_out, axes=(-1,), direction="FFTW_BACKWARD") - except ValueError: - raise ValueError( - "incompatible array types/shapes. See function documentation for allowed values" - ) - - typesig = "void(" + str(w_in.dtype) + "[:, :], " + str(w_out.dtype) + "[:, :])" - sizesig = "(m, n)->(m, n)" if w_in.shape == w_out.shape else "(m, n),(m, l)" - - @guvectorize( - [typesig], - sizesig, - **nb_kwargs( - cache=False, - forceobj=True, - ), - ) - def inv_dft(wf_in: np.ndarray, dft_out: np.ndarray) -> None: - idft_fun(wf_in, dft_out) - - return inv_dft - - -def psd(w_in: np.ndarray, w_out: np.ndarray) -> Callable: - """Perform discrete Fourier transforms using the FFTW library, and use it to get - the power spectral density. - - Parameters - ---------- - w_in - the input waveform. - w_out - the output fourier transform. - - JSON Configuration Example - -------------------------- - - .. code-block :: json - - "wf_psd": { - "function": "psd", - "module": "dspeed.processors", - "args": ["wf", "wf_psd"], - "init_args": ["wf", "wf_psd"] - } - - Note - ---- - FFTW optimizes the FFT algorithm based on the size of the arrays, with SIMD - parallelized commands. This optimization requires initialization, so this - is a factory function that returns a Numba gufunc that performs the FFT. - FFTW works on fixed memory buffers, so you must tell it what memory to use - ahead of time. When using this with - :class:`~.dsp.processing_chain.ProcessingChain`, the output waveform's size, - dtype and coordinate grid units can be set automatically. The - possible `dtypes` for the input/outputs are: - - =============================== ========= ============================ ============= - :class:`numpy.dtype` Size :class:`numpy.dtype` Size - ------------------------------- --------- ---------------------------- ------------- - ``complex64`` :math:`n` ``float32``/``float`` :math:`n` - ``complex128`` :math:`n` ``float64``/``double`` :math:`n` - ``complex256``/``clongdouble`` :math:`n` ``float128``/``longdouble`` :math:`n` - ``float32``/``float`` :math:`n` ``float32``/``float`` :math:`n/2+1` - ``float64``/``double`` :math:`n` ``float64``/``double`` :math:`n/2+1` - ``float128``/``longdouble`` :math:`n` ``float128``/``longdouble`` :math:`n/2+1` - =============================== ========= ============================ ============= - """ - # if we have a ProcChainVar, set up the output and get numpy arrays - if isinstance(w_in, ProcChainVarBase) and isinstance(w_out, ProcChainVarBase): - c = w_in.dtype.kind - s = w_in.dtype.itemsize - if c == "f": - w_out.update_auto( - shape=w_in.shape[:-1] + (w_in.shape[-1] // 2 + 1,), - dtype=np.dtype(f"f{s}"), - period=1.0 / w_in.period / w_in.shape[-1], - ) - elif c == "c": - w_out.update_auto( - shape=w_in.shape, - dtype=np.dtype(f"f{s//2}"), - period=1.0 / w_in.period / w_in.shape[-1], - ) - w_in = w_in.buffer - w_out = w_out.buffer - - # build intermediate array for the dft, which will be abs'd to get the PSD - w_dft = np.ndarray(w_out.shape, np.dtype(f"c{w_in.dtype.itemsize*2}")) - try: - dft_fun = FFTW(w_in, w_dft, axes=(-1,), direction="FFTW_FORWARD") - except ValueError: - raise ValueError( - "incompatible array types/shapes. See function documentation for allowed values" - ) - - typesig = "void(" + str(w_in.dtype) + "[:, :], " + str(w_out.dtype) + "[:, :])" - sizesig = "(m, n)->(m, n)" if w_in.shape == w_out.shape else "(m, n),(m, l)" - - @guvectorize( - [typesig], - sizesig, - **nb_kwargs( - cache=False, - forceobj=True, - ), - ) - def psd(wf_in: np.ndarray, psd_out: np.ndarray) -> None: - dft_fun(wf_in, w_dft) - np.abs(w_dft, psd_out) - - return psd diff --git a/tests/configs/icpc-dsp-config.json b/tests/configs/icpc-dsp-config.json index a30a128..d3b3e05 100644 --- a/tests/configs/icpc-dsp-config.json +++ b/tests/configs/icpc-dsp-config.json @@ -34,7 +34,6 @@ "zacEmax", "zacEftp", "cuspEftp", - "wf_psd" ], "processors": { "tp_min, tp_max, wf_min, wf_max": { @@ -311,16 +310,9 @@ "args": ["wf_trap2", "tp_0_est + 8.096*us", "'l'", "trapQftp"], "unit": "ADC" }, - "QDrift": { - "function": "multiply", - "module": "numpy", - "args": ["trapQftp", "(4*us)/waveform.period", "QDrift"], - "unit": "ADC" - }, + "QDrift": "trapQftp * 16", "dt_eff": { - "function": "divide", - "module": "numpy", - "args": ["QDrift", "trapTmax", "dt_eff"], + "function": "QDrift/trapTmax", "unit": "ns" }, "wf_le": { @@ -359,11 +351,5 @@ "args": ["tp_0_est", "tp_aoe_max/16", "tp_aoe_samp"], "unit": "ns" }, - "wf_psd": { - "function": "psd", - "module": "dspeed.processors", - "args": ["wf_blsub", "wf_psd"], - "init_args": ["wf_blsub", "wf_psd"] - } } } diff --git a/tests/processors/test_fftw.py b/tests/processors/test_fftw.py deleted file mode 100644 index f77eddc..0000000 --- a/tests/processors/test_fftw.py +++ /dev/null @@ -1,88 +0,0 @@ -import numpy as np -import pytest - -from dspeed.processors import dft, inv_dft, psd - - -def test_dft(compare_numba_vs_python): - """Testing function for the discrete fourier transform.""" - - # set up arrays to use - w_in = np.zeros(shape=(16, 100), dtype="float32") - w_dft = np.zeros(shape=(16, 51), dtype="complex64") - - # ensure the DSPFatal is raised for incorrect shaps/types - with pytest.raises(ValueError): - dft(w_in, np.zeros_like(w_in)) - - # ensure that a valid input gives the expected output - w_expected = np.zeros_like(w_dft) - w_expected[:, 0] = 100.0 - - dft_func = dft(w_in, w_dft) - w_in[:] = 1.0 - - assert np.allclose( - compare_numba_vs_python(dft_func, w_in, w_dft), - w_expected, - ) - - # ensure that if there is a nan in w_in, all nans are outputted - w_in[:, 10] = np.nan - assert np.all(np.isnan(compare_numba_vs_python(dft_func, w_in, w_dft))) - - -def test_inv_dft(compare_numba_vs_python): - """Testing function for the inverse discrete fourier transform.""" - - # set up arrays to use - w_in = np.zeros(shape=(16, 51), dtype="complex64") - w_inv_dft = np.zeros(shape=(16, 100), dtype="float32") - - # ensure the DSPFatal is raised for incorrect shaps/types - with pytest.raises(ValueError): - inv_dft(w_in, np.zeros(shape=(16, 51), dtype="float32")) - - # ensure that a valid input gives the expected output - w_expected = np.zeros_like(w_inv_dft) - w_expected[:, 0] = 1.0 - - inv_dft_func = inv_dft(w_in, w_inv_dft) - w_in[:] = 1.0 - - assert np.allclose( - compare_numba_vs_python(inv_dft_func, w_in, w_inv_dft), - w_expected, - ) - - # ensure that if there is a nan in w_in, all nans are outputted - w_in[:, 10] = np.nan - assert np.all(np.isnan(compare_numba_vs_python(inv_dft_func, w_in, w_inv_dft))) - - -def test_psd(compare_numba_vs_python): - """Testing function for the power spectral density.""" - - # set up arrays to use - w_in = np.zeros(shape=(16, 100), dtype="float32") - w_psd = np.zeros(shape=(16, 51), dtype="float32") - - # ensure the DSPFatal is raised for incorrect shaps/types - with pytest.raises(ValueError): - psd(w_in, np.zeros_like(w_in)) - - # ensure that a valid input gives the expected output - w_expected = np.zeros_like(w_psd) - w_expected[:, 0] = 100.0 - - psd_func = psd(w_in, w_psd) - w_in[:] = 1.0 - - assert np.allclose( - compare_numba_vs_python(psd_func, w_in, w_psd), - w_expected, - ) - - # ensure that if there is a nan in w_in, all nans are outputted - w_in[:, 10] = np.nan - assert np.all(np.isnan(compare_numba_vs_python(psd_func, w_in, w_psd))) From b67ca0e784b2e6c9cfccf1d26baea5e7c4286868 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 28 Apr 2024 22:06:40 +0000 Subject: [PATCH 3/4] style: pre-commit fixes --- tests/configs/icpc-dsp-config.json | 4 ++-- tests/processors/test_time_point_thresh.py | 19 ++++++++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/tests/configs/icpc-dsp-config.json b/tests/configs/icpc-dsp-config.json index d3b3e05..a8b8fce 100644 --- a/tests/configs/icpc-dsp-config.json +++ b/tests/configs/icpc-dsp-config.json @@ -33,7 +33,7 @@ "cuspEmax", "zacEmax", "zacEftp", - "cuspEftp", + "cuspEftp" ], "processors": { "tp_min, tp_max, wf_min, wf_max": { @@ -350,6 +350,6 @@ "module": "numpy", "args": ["tp_0_est", "tp_aoe_max/16", "tp_aoe_samp"], "unit": "ns" - }, + } } } diff --git a/tests/processors/test_time_point_thresh.py b/tests/processors/test_time_point_thresh.py index 5e4be9d..0c783f5 100644 --- a/tests/processors/test_time_point_thresh.py +++ b/tests/processors/test_time_point_thresh.py @@ -194,7 +194,7 @@ def test_bi_level_zero_crossing_time_points(compare_numba_vs_python): # ensure that if there is a nan in w_in, all nans are outputted w_in = np.ones(100) w_in[4] = np.nan - n_out = np.zeros(1, 'uint32') + n_out = np.zeros(1, "uint32") t_out = np.zeros(5) pol_out = np.zeros(5) bi_level_zero_crossing_time_points(w_in, 100, 100, 100, 0, n_out, pol_out, t_out) @@ -324,7 +324,14 @@ def test_bi_level_zero_crossing_time_points(compare_numba_vs_python): t_trig_times_out = np.zeros(5) pol_out = np.zeros(5) bi_level_zero_crossing_time_points( - -1 * np.linspace(-1, 100, 101), 4, -4, gate_time, 0, n_out, pol_out, t_trig_times_out + -1 * np.linspace(-1, 100, 101), + 4, + -4, + gate_time, + 0, + n_out, + pol_out, + t_trig_times_out, ) assert np.isnan(t_trig_times_out).all() assert np.isnan(pol_out).all() @@ -369,13 +376,11 @@ def test_bi_level_zero_crossing_time_points(compare_numba_vs_python): assert int(pol_out[0]) == 1 # Check for overflow. This should not fail and should return n_crossings greater than the length of the outputs - w_in = np.zeros(100, 'float')*10 + w_in = np.zeros(100, "float") * 10 w_in[::2] = -10 w_in[1::2] = 10 pol_out = np.zeros(30) t_trig_out = np.zeros(30) - bi_level_zero_crossing_time_points( - w_in, 1, 1, 10, 0, n_out, pol_out, t_trig_out - ) - assert np.all(pol_out==0) + bi_level_zero_crossing_time_points(w_in, 1, 1, 10, 0, n_out, pol_out, t_trig_out) + assert np.all(pol_out == 0) assert n_out[0] == 49 From 43dd6f75e831b70756fe007ca6eecdccb6f90405 Mon Sep 17 00:00:00 2001 From: Ian Guinn Date: Sun, 28 Apr 2024 18:25:46 -0400 Subject: [PATCH 4/4] Removed deprecated ast types --- src/dspeed/processing_chain.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/dspeed/processing_chain.py b/src/dspeed/processing_chain.py index 85a9464..6b65484 100644 --- a/src/dspeed/processing_chain.py +++ b/src/dspeed/processing_chain.py @@ -783,12 +783,6 @@ def _parse_expr( else: ProcessingChainError("only 1D arrays are supported: " + expr) - elif isinstance(node, ast.Num): - return node.n - - elif isinstance(node, ast.Str): - return node.s - elif isinstance(node, ast.Constant): return node.value