def test_dtype(): """Ensure `cwt` and `ssq_cwt` compute at appropriate precision depending on `Wavelet.dtype`, returning float32 & complex64 arrays for single precision. """ os.environ['SSQ_GPU'] = '0' wav32, wav64 = Wavelet(dtype='float32'), Wavelet(dtype='float64') x = np.random.randn(256) outs32 = ssq_cwt(x, wav32) outs64 = ssq_cwt(x, wav64) outs32_o2 = ssq_cwt(x, wav32, order=2) names = ('Tx', 'Wx', 'ssq_freqs', 'scales', 'w', 'dWx') outs32 = {k: v for k, v in zip(names, outs32)} outs32_o2 = {k: v for k, v in zip(names, outs32_o2)} outs64 = {k: v for k, v in zip(names, outs64)} for k, v in outs32.items(): if k == 'ssq_freqs': assert v.dtype == np.float64, ("float32", k, v.dtype) continue assert v.dtype in (np.float32, np.complex64), ("float32", k, v.dtype) for k, v in outs32_o2.items(): if k == 'ssq_freqs': assert v.dtype == np.float64, ("float32", k, v.dtype) continue assert v.dtype in (np.float32, np.complex64), ("float32", k, v.dtype) for k, v in outs64.items(): if k == 'ssq_freqs': assert v.dtype == np.float64, ("float32", k, v.dtype) continue assert v.dtype in (np.float64, np.complex128), ("float64", k, v.dtype)
def test_wavelet_info(): for parallel in ('0', '1'): os.environ['SSQ_PARALLEL'] = parallel Wavelet(('gmw', {'norm': 'bandpass'})).info() Wavelet(('gmw', {'norm': 'energy'})).info() Wavelet(('gmw', {'norm': 'bandpass', 'order': 1})).info() Wavelet(('gmw', {'norm': 'energy', 'order': 1})).info() for name in ('morlet', 'bump', 'cmhat', 'hhhat'): Wavelet(name).info()
def test_utils(): os.environ['SSQ_GPU'] = '0' _ = utils.buffer(np.random.randn(20), 4, 1) wavelet = Wavelet(('morlet', {'mu': 6})) _ = wavelets.center_frequency(wavelet, viz=1) _ = wavelets.freq_resolution(wavelet, viz=1, scale=3, force_int=0) _ = wavelets.time_resolution(wavelet, viz=1) xh = np.random.randn(128) xhs = np.zeros(xh.size) wavelets._aifftshift_even(xh, xhs) wavelets._afftshift_even(xh, xhs) _ = utils.padsignal(xh, padlength=len(xh) * 2, padtype='symmetric') _ = utils.padsignal(xh, padlength=len(xh) * 2, padtype='wrap') x2d = np.random.randn(4, 64) _ = utils.padsignal(x2d, padlength=96, padtype='symmetric') g = np.ones((128, 200)) utils.unbuffer(g, xh, 1, n_fft=len(xh), N=None, win_exp=0) utils.unbuffer(g, xh, 1, n_fft=len(xh), N=g.shape[1], win_exp=2) scales = utils.process_scales('log', 1024, Wavelet()) _ = utils.find_downsampling_scale(Wavelet(), scales, method='any', viz_last=1) _ = utils.find_downsampling_scale(Wavelet(), scales, method='all') #### errors / warnings ################################################### pass_on_error(utils.find_max_scale, 1, 1, -1, -1) pass_on_error(utils.cwt_scalebounds, 1, 1, preset='etc', min_cutoff=0) pass_on_error(utils.cwt_scalebounds, 1, 1, min_cutoff=-1) pass_on_error(utils.cwt_scalebounds, 1, 1, min_cutoff=.2, max_cutoff=.1) pass_on_error(utils.cwt_scalebounds, 1, 1, cutoff=0) pass_on_error(utils.cwt_utils._assert_positive_integer, -1, 'w') pass_on_error(utils.infer_scaletype, 1) pass_on_error(utils.infer_scaletype, np.array([1])) pass_on_error(utils.infer_scaletype, np.array([1., 2., 5.])) pass_on_error(utils._process_fs_and_t, 1, np.array([1]), 2) pass_on_error(utils._process_fs_and_t, 1, np.array([1., 2, 4]), 3) pass_on_error(utils._process_fs_and_t, -1, None, 1) pass_on_error(utils.make_scales, 128, scaletype='banana') pass_on_error(utils.padsignal, np.random.randn(3, 4, 5))
def test_cwt_vs_stft(): os.environ['SSQ_GPU'] = '0' # (N, beta, NW): (512, 42.5, 255); (256, 21.5, 255) N = 256 #512 signals = 'all' snr = 5 n_fft = N win_len = n_fft #//2 tsigs = TestSignals(N=N, snr=snr) wavelet = Wavelet(('GMW', {'beta': 21.5})) NW = win_len // 2 - 1 window = np.abs(sig.windows.dpss(win_len, NW)) # window = np.pad(window, win_len//2) window_name = 'DPSS' config_str = '\nNW=%s' % NW # ensure `wavelet` and `window` have ~same time & frequency resolutions # TODO make function to auto-find matching wavelet given window & vice versa print("std_w, std_t, harea\nwavelet: {:.4f}, {:.4f}, {:.8f}" "\nwindow: {:.4f}, {:.4f}, {:.8f}".format( wavelet.std_w, wavelet.std_t, wavelet.harea, *window_resolution(window))) tsigs.cwt_vs_stft(wavelet, window, signals=signals, N=N, win_len=win_len, n_fft=n_fft, window_name=window_name, config_str=config_str)
def time_ssq_cwt(x, dtype, scales, cache_wavelet, ssq_freqs): wavelet = Wavelet(dtype=dtype) kw = dict(wavelet=wavelet, scales=scales, ssq_freqs=ssq_freqs) if cache_wavelet: for _ in range(3): # warmup run _ = ssq_cwt(x, cache_wavelet=True, **kw) del _ gc.collect() return timeit(lambda: ssq_cwt(x, cache_wavelet=cache_wavelet, **kw))
def time_cwt(x, dtype, scales, cache_wavelet): wavelet = Wavelet(dtype=dtype) if cache_wavelet: for _ in range(3): # warmup run _ = cwt(x, wavelet, scales=scales, cache_wavelet=True) del _ gc.collect() return timeit( lambda: cwt(x, wavelet, scales=scales, cache_wavelet=cache_wavelet))
def test_wavcomp(): os.environ['SSQ_GPU'] = '0' tsigs = TestSignals(N=256) wavelets = [ Wavelet(('gmw', { 'beta': 5 })), Wavelet(('gmw', { 'beta': 22 })), ] tsigs.wavcomp(wavelets) # test name-param pair, and ability to auto-set `N` N_all = [256, None] signals_all = [[('#echirp', dict(fmin=.1))], [('lchirp', dict(fmin=1, fmax=60, tmin=0, tmax=5))]] for N, signals in zip(N_all, signals_all): tsigs.wavcomp(wavelets, signals=signals, N=N)
def test_misc(): _ = cwt(np.random.randn(128), 'gmw', cache_wavelet=True) _ = cwt(np.random.randn(128), Wavelet(), cache_wavelet=True, vectorized=False) _ = ssq_stft(np.random.randn(100), get_w=1, get_dWx=1) pass_on_error(cwt, np.random.randn(2, 2, 2)) pass_on_error(cwt, 5) pass_on_error(ssq_stft, np.random.randn(2, 2, 2), get_w=1)
def test_gpu(): """Test that TestSignals can run on GPU.""" try: import torch torch.tensor(1., device='cuda') except: return N = 256 tsigs = TestSignals(N=N) window = np.abs(sig.windows.dpss(N, N // 2 - 1)) signals = 'par-lchirp' os.environ['SSQ_GPU'] = '1' wavelet = Wavelet() tsigs.cwt_vs_stft(wavelet, window, signals=signals, N=N) os.environ['SSQ_GPU'] = '0'
def test_phase_cwt(): os.environ['SSQ_GPU'] = '0' x = TestSignals(N=1000).par_lchirp()[0] x += x[::-1] wavelet = Wavelet() scales = process_scales('log', len(x), wavelet, nv=32)[:240] Wx, _, dWx = cwt(x, wavelet, scales=scales, derivative=True, cache_wavelet=1) for dtype in ('complex128', 'complex64'): # Wx = np.random.randn(100, 8192).astype(dtype) * (1 + 2j) # dWx = np.random.randn(100, 8192).astype(dtype) * (2 - 1j) Wx, dWx = Wx.astype(dtype), dWx.astype(dtype) if CAN_GPU: Wxt = torch.tensor(Wx, device='cuda') dWxt = torch.tensor(dWx, device='cuda') gamma = 1e-2 _out = (dWx / Wx).imag / (2 * np.pi) _out[np.abs(Wx) < gamma] = np.inf _out = np.abs(_out) out0 = phase_cwt_cpu(Wx, dWx, gamma, parallel=False) out1 = phase_cwt_cpu(Wx, dWx, gamma, parallel=True) if CAN_GPU: out2 = phase_cwt_gpu(Wxt, dWxt, gamma).cpu().numpy() with np.errstate(invalid='ignore'): mape0_ = _noninf_mean(np.abs(_out - out0) / np.abs(_out)) mape01 = _noninf_mean(np.abs(out0 - out1) / np.abs(out0)) if CAN_GPU: mape02 = _noninf_mean(np.abs(out0 - out2) / np.abs(out0)) assert np.allclose(out0, _out), ("base", dtype, mape0_) assert np.allclose(out0, out1), ("parallel", dtype, mape01) if CAN_GPU: assert np.allclose(out0, out2), ("gpu", dtype, mape02)
signals = [ 'am-cosine', ('hchirp', dict(fmin=.2)), ('sine:am-cosine', (dict(f=32, phi0=1), dict(amin=.3))), ] tsigs.demo(signals, N=2048) #%%# With `dft` ################## tsigs.demo(signals, dft='rows') tsigs.demo(signals, dft='cols') #%%# Viz CWT & SSQ_CWT with different wavelets ############################### tsigs = TestSignals(N=2048) wavelets = [ Wavelet(('gmw', { 'beta': 60 })), Wavelet(('gmw', { 'beta': 5 })), ] tsigs.wavcomp(wavelets, signals='all') #%%# tsigs.wavcomp(wavelets, signals=[('#echirp', dict(fmin=.1))], N=2048) #%%# Viz CWT vs STFT (& SSQ'd) ############################################### # (N, beta, NW): (512, 42.5, 255); (256, 21.5, 255) N = 2048 signals = 'all'
# 'log-piecewise' lowers low-frequency redundancy; see # https://github.com/OverLordGoldDragon/ssqueezepy/issues/29#issuecomment-778526900 scaletype = 'log-piecewise' # one of: 'minimal', 'maximal', 'naive' (not recommended) preset = 'maximal' # number of voices (wavelets per octave); more = more scales nv = 32 # downsampling factor for higher scales (used only if `scaletype='log-piecewise'`) downsample = 4 # show this many of lowest-frequency wavelets show_last = 20 #%%## Make scales ############################################################ # `cwt` uses `p2up`'d N internally M = p2up(N)[0] wavelet = Wavelet(wavelet, N=M) min_scale, max_scale = cwt_scalebounds(wavelet, N=len(x), preset=preset) scales = make_scales(N, min_scale, max_scale, nv=nv, scaletype=scaletype, wavelet=wavelet, downsample=downsample) #%%# Visualize scales ######################################################## viz(wavelet, scales, scaletype, show_last, nv) wavelet.viz('filterbank', scales=scales) #%%# Show applied ############################################################
def _wavelet(name='gmw', **kw): return Wavelet((name, kw))
# -*- coding: utf-8 -*- """Experimental feature example.""" if __name__ != '__main__': raise Exception("ran example file as non-main") import numpy as np from ssqueezepy import TestSignals, ssq_cwt, Wavelet from ssqueezepy.visuals import imshow from ssqueezepy.experimental import phase_ssqueeze #%% x = TestSignals(N=2048).par_lchirp()[0] x += x[::-1] wavelet = Wavelet() Tx0, Wx, _, scales, *_ = ssq_cwt(x, wavelet, get_dWx=1) Tx1, *_ = phase_ssqueeze(Wx, wavelet=wavelet, scales=scales, flipud=1) adiff = np.abs(Tx0 - Tx1) print(adiff.mean(), adiff.max(), adiff.sum()) #%% # main difference near boundaries; see `help(trigdiff)` w/ `rpadded=False` imshow(Tx1, abs=1)
def test_anim(): # bare minimally (still takes long, but covers many lines of code) wavelet = Wavelet(('morlet', {'mu': 6})) wavelet.viz('anim:time-frequency', N=8, scales=np.linspace(10, 20, 3))
num = str(len(x))[:-3] + 'k' return { num: '', f'{num}-cwt': time_cwt(x, dtype, scales, cache_wavelet), f'{num}-stft': time_stft(x, dtype, n_fft), f'{num}-ssq_cwt': time_ssq_cwt(x, dtype, scales, cache_wavelet, ssq_freqs), f'{num}-ssq_stft': time_ssq_stft(x, dtype, n_fft) } #%%# Setup ################################################################### # warmup x = np.random.randn(1000) for dtype in ('float32', 'float64'): wavelet = Wavelet(dtype=dtype) _ = ssq_cwt(x, wavelet, cache_wavelet=False) _ = ssq_stft(x, dtype=dtype) del _, wavelet #%%# Prepare reusable parameters such that STFT & CWT output shapes match #### N0, N1 = 10000, 160000 # selected such that CWT pad length ratios are same n_rows = 300 n_fft = n_rows * 2 - 2 wavelet = Wavelet() scales = process_scales('log-piecewise', N1, wavelet=wavelet)[:n_rows] ssq_freqs = _compute_associated_frequencies(scales, N1, wavelet, 'log-piecewise',
def test_wavelets(): os.environ['SSQ_GPU'] = '0' for wavelet in ('morlet', ('morlet', {'mu': 4}), 'bump'): wavelet = Wavelet(wavelet) wavelet = Wavelet(('morlet', {'mu': 5})) wavelet.viz(name='overview') wavelet.info(nondim=1) wavelet.info(nondim=0) #### Visuals ############################################################# for name in wavelet.VISUALS: if 'anim:' in name: # heavy-duty computations, skip animating kw = {'testing': True} else: kw = {} try: wavelet.viz(name, N=256, **kw) except TypeError as e: if "positional argument" not in str(e): raise TypeError(e) try: wavelet.viz(name, scale=10, N=256, **kw) except TypeError as e: if "positional argument" not in str(e): raise TypeError(e) wavelet.viz(name, scales='log', N=256, **kw) _ = utils.cwt_scalebounds(wavelet, N=512, viz=3) #### misc ################################################################ wavelet = Wavelet(lambda x: x) _ = wavelets._xifn(scale=10, N=128)