## Mathmatical expression

For scientific purpose, we sometime need to shift phase of time series with specfic angles. To acheive this, we can transform the time series into freqeuency domain with $$F(\omega) = \int_{-\omega}^{\omega} f(t) e^{-i \omega t} dt$$

where $F(\omega)$ as Fourier spectrum of signal $f(t)$. Thus, the phase shifted Fourier spectrum $F_{sh}$ is

$$F_{sh}(\omega) = F(\omega) * e^{-i \alpha}$$

in thich $\alpha$ indicates shifted angle.

## Numerical experiment

Previous approach could be applied with below Python code

  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  # -*- coding: utf-8 -*- #------------------------------------------------------------------------------- # Purpose: Shown edge error in performing phase shift # Status: Developing # Dependence: Python 3.6 # Version: ALPHA # Created Date: 22:11h, 29/07/2018 # Usage: python test.py # Author: Xiao Xiao, https://github.com/SeisPider # Email: xiaox.seis@gmail.com # Copyright (C) 2017-2018 Xiao Xiao #------------------------------------------------------------------------------- from numpy.fft import rfft, irfft, rfftfreq from scipy.signal import hilbert import numpy as np import matplotlib.pyplot as plt import matplotlib font = {'size' : 18} matplotlib.rc('font', **font) def phase_shift(iptsignal, angle, dt): """Perform phase shift of arbitary angle Parameter ========= iptsignal : numpy.array input signal angle : float angle to shift signal, in degree dt : float time step """ # Resolve the signal's fourier spectrum spec = rfft(iptsignal) freq = rfftfreq(iptsignal.size, d=dt) # Perform phase shift in freqeuency domain spec *= np.exp(1.0j * np.deg2rad(angle)) # Inverse FFT back to time domain phaseshift = irfft(spec, n=len(iptsignal)) return phaseshift if __name__ == '__main__': # Define Time range time = np.arange(0, 10000) signal = np.cos(time / 100.0) sinsignal = np.sin(time / 100.0) # Shift angle and time step angle, dt = -90, 1 phsignal = phase_shift(signal, angle, dt) # Comparasion between Personal shifted and theoretical result fig, axes = plt.subplots(nrows=2, ncols=1, figsize=(12, 14)) axes[0].plot(time, signal, label="Cosine (raw)") axes[0].plot(time, sinsignal, label="Sine") axes[0].plot(time, phsignal, "--", label="Shift") axes[0].set_xlabel("Time") axes[0].set_ylabel("Amplitude") axes[0].set_title("Comparison between Sinudoidal function and shifted signal") axes[0].legend() # Comparasion between Personal shifted and Hilbert transform result axes[1].plot(time, signal, label="Cosine (raw)") axes[1].plot(time, phsignal, label="Shift") axes[1].plot(time, np.imag(hilbert(signal)), "--", label="Hilbert") axes[1].set_xlabel("Time") axes[1].set_ylabel("Amplitude") axes[1].set_title("Comparison between shifted signal and Hilbert transform format") axes[1].legend() plt.show()

With an output like below,

Using a cosine-dominated signal for benchmark, the theoretical phase shifted signal shold be a sine signal with same frequency. However, the phase shifted signal shows great differences in edge part refering to the theoretical one and is the same as the signal computed from numerical hilbert tranformation result.

warning

So, it’s dangerous to numerically shift phases and completely wrong in edge part, around 2~3 times of the maximum peroid.

## Change log.

• 2018-07-29: Initial version