Hướng dẫn phase shift in python - chuyển pha trong python

Bạn đã không thực hiện một sự thay đổi pha.

Những gì bạn đã làm là thêm một vector 6000, giả sử p, với giá trị không đổi p (i) = j π thành v, fft của v.

Hãy viết ṽ = V + P.

Do tính tuyến tính của FFT (và của IFFT), những gì bạn đã gọi là back_again

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

Tất nhiên, ở đâu, p = ifft (p) là sự khác biệt ____10 - bây giờ, hãy kiểm tra xem P ...

In [51]: P = np.pi*1j*np.ones(6000) 
    ...: p = np.fft.ifft(P) 
    ...: plt.plot(p.real*10**16, label='real(p)*10**16') 
    ...: plt.plot(p.imag, label='imag(p)') 
    ...: plt.legend();

Hướng dẫn phase shift in python - chuyển pha trong python

Như bạn có thể thấy, bạn đã sửa đổi

In [61]: import matplotlib.pyplot as plt 
    ...: import numpy as np                                                                                           
In [62]: def multiple_formatter(x, pos, den=60, number=np.pi, latex=r'\pi'): 
             ... # search on SO for an implementation
In [63]: def plot(t, x): 
    ...:     fig, ax = plt.subplots() 
    ...:     ax.plot(t, x) 
    ...:     ax.xaxis.set_major_formatter(plt.FuncFormatter(multiple_formatter)) 
    ...:     ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2)) 
    ...:     ax.xaxis.set_minor_locator(plt.MultipleLocator(np.pi / 4)) 
1 bằng cách thêm một thành phần thực của ṽ về cơ bản là tiếng ồn bằng số trong tính toán của IFFT (do đó không có thay đổi trong cốt truyện, điều đó mang lại cho bạn phần thực của back_again) và một sự đột biến tưởng tượng duy nhất, nó Chiều cao không có gì đáng ngạc nhiên bằng π, với t = 0.imaginary spike, its height unsurprisingly equal to π, for t=0.

Biến đổi của một hằng số là một tăng đột biến ở ω = 0, chất chống biến dạng của hằng số (trong miền tần số) là tăng đột biến ở t = 0.

Mặt khác, nếu bạn nhân mỗi thuật ngữ FFT với một hằng số, bạn cũng nhân tín hiệu miền thời gian với cùng một hằng số (hãy nhớ, FFT và IFFT là tuyến tính).

Để làm những gì bạn muốn, bạn phải nhớ rằng một sự thay đổi trong miền thời gian chỉ là sự chập (tròn) của tín hiệu (định kỳ) với tăng đột biến theo thời gian, vì vậy bạn phải nhân FFT của tín hiệu với FFT của sự thay đổi tăng đột biến.

Vì biến đổi Fourier của phân phối dirac (T-A) là exp (-iΩa), bạn phải nhân mỗi thuật ngữ FFT của tín hiệu với một thuật ngữ phụ thuộc tần số, exp (-iΩa) = cos (Ωa) -i · sin (Ωa) (Lưu ý: Tất nhiên mỗi một trong số các thuật ngữ nhân này có biên độ đơn vị).


Một ví dụ

Một số sơ bộ

In [61]: import matplotlib.pyplot as plt 
    ...: import numpy as np                                                                                           
In [62]: def multiple_formatter(x, pos, den=60, number=np.pi, latex=r'\pi'): 
             ... # search on SO for an implementation
In [63]: def plot(t, x): 
    ...:     fig, ax = plt.subplots() 
    ...:     ax.plot(t, x) 
    ...:     ax.xaxis.set_major_formatter(plt.FuncFormatter(multiple_formatter)) 
    ...:     ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2)) 
    ...:     ax.xaxis.set_minor_locator(plt.MultipleLocator(np.pi / 4)) 

Một chức năng để tính toán FT riêng biệt của phân phối DIRAC tập trung vào

In [61]: import matplotlib.pyplot as plt 
    ...: import numpy as np                                                                                           
In [62]: def multiple_formatter(x, pos, den=60, number=np.pi, latex=r'\pi'): 
             ... # search on SO for an implementation
In [63]: def plot(t, x): 
    ...:     fig, ax = plt.subplots() 
    ...:     ax.plot(t, x) 
    ...:     ax.xaxis.set_major_formatter(plt.FuncFormatter(multiple_formatter)) 
    ...:     ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2)) 
    ...:     ax.xaxis.set_minor_locator(plt.MultipleLocator(np.pi / 4)) 
3 trong một khoảng thời gian
In [61]: import matplotlib.pyplot as plt 
    ...: import numpy as np                                                                                           
In [62]: def multiple_formatter(x, pos, den=60, number=np.pi, latex=r'\pi'): 
             ... # search on SO for an implementation
In [63]: def plot(t, x): 
    ...:     fig, ax = plt.subplots() 
    ...:     ax.plot(t, x) 
    ...:     ax.xaxis.set_major_formatter(plt.FuncFormatter(multiple_formatter)) 
    ...:     ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2)) 
    ...:     ax.xaxis.set_minor_locator(plt.MultipleLocator(np.pi / 4)) 
4

In [64]: def shift(n, N): 
    ...:     s = np.zeros(N) 
    ...:     s[n] = 1.0 
    ...:     return np.fft.fft(s)                                                                                     

Hãy vẽ một tín hiệu và tín hiệu thay đổi

In [65]: t = np.arange(4096)*np.pi/1024                                                                               
In [66]: v0 = np.sin(t)                                                                                               
In [67]: v1 = np.sin(t-np.pi/4)                                                                                       
In [68]: f, a = plot(t, v0)                                                                                           
In [69]: a.plot(t, v1, label='shifted by $\\pi/4$');                                                                   
In [70]: a.legend();

Hướng dẫn phase shift in python - chuyển pha trong python

Bây giờ tính toán FFT của Spike chính xác (lưu ý rằng π/4 = (4π)/16), FFT của tín hiệu đã thay đổi, IFFT của FFT của S.S. Và cuối cùng vạch ra kết quả của chúng tôi

In [71]: S = shift(4096//16-1, 4096)                                                                                  
In [72]: VS = np.fft.fft(v0)*S                                                                                        
In [73]: vs = np.fft.ifft(VS)                                                                                         
In [74]: f, ay = plot(t, v0)                                                                                          
In [75]: ay.plot(t, vs.real, label='shifted in frequency domain');                                                    
In [76]: ay.legend();

Hướng dẫn phase shift in python - chuyển pha trong python

Kỹ thuật đơn giản nhất trong trường hợp của bạn là chỉ cần tính toán tương quan $ r $ của tín hiệu có nghĩa sóng.$r$ of de-meaned signals, then get the phase difference as $\phi=\arccos(r/\pi)$ if the signals are harmonic, i.e. single frequency sine waves.

Một cách khác để làm điều này là với chức năng tương quan chéo. Ý tưởng là tính toán mối tương quan giữa một tín hiệu và tín hiệu thứ hai bị trễ. Khi số độ trễ gần nhất với sự thay đổi pha, bạn sẽ nhận được mối tương quan tối đa. Ưu điểm của kỹ thuật này là nó không phụ thuộc vào hình dạng tín hiệu của bạn, trong khi phương pháp đầu tiên là tốt nhất cho các tín hiệu điều hòa.

Phương pháp tương quan

Tại sao điều này nên làm việc cho bạn? Ở tần số lấy mẫu là 500 MHz, bạn có ít nhất 36 điểm mỗi sóng tín hiệu 13,56 MHz của mình. Với 20000 mẫu cung cấp cho bạn hàng trăm sóng đầy đủ được đo, điều đó có nghĩa là trung bình của tín hiệu sẽ rất gần với các phương tiện và sóng một phần ở đầu và cuối mẫu của bạn sẽ không quan trọng. Do đó, sau khi khử các tín hiệu, mối tương quan chỉ đơn giản là sôi lên với phương trình sau: $$ r \ xấp xỉ \ frac {\ int_0^{2 \ pi} sin (x) sin (x+\ Phi)} {2 \ pi} sin (x)^2} = \ cos (\ Phi) $$$$r\approx\frac{\int_0^{2\pi}sin(x)sin(x+\phi)}{\int_0^{2\pi}sin(x)^2}=\cos(\phi)$$

Dưới đây là một đoạn mã Python để chứng minh cách thức hoạt động của tỷ lệ nhiễu/tín hiệu 10%.

Nhập NUMPY dưới dạng toán học nhập khẩu NP

# create fake data
nsr = 1e-1
r = np.random.normal(size=(20000,2)) * nsr
phdiff = math.pi * np.random.uniform()
print('true phase diff (radians):', phdiff, '\t(degrees):', phdiff / (2 * math.pi) * 360)
omega = 13.56e6
t = np.arange(20000) / 500e6
rdata = np.zeros((len(t), 2))
ph0 = 2 * math.pi * np.random.uniform()
rdata[:,0] = np.sin(2 * math.pi * omega * t + ph0)
rdata[:,1] = np.sin(2 * math.pi * omega * t + phdiff + ph0)
rdata = rdata + r

# scale
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(rdata)
data = scaler.transform(rdata)

import matplotlib.pyplot as plt
plt.figure()
plt.plot(data[1:100,:])
plt.show()

# phase difference determination
plt.figure(figsize=(4,4))
plt.title('Phase diagram')
plt.scatter(data[1:100,0],data[1:100,1])
plt.show()

c = np.cov(np.transpose(data))
print('cov: ', c)
phi = np.arccos(c[0,1] )
print('phase estimate (radians): ', phi, '(degrees): ', phi / math.pi * 180)

Output:

true phase diff (radians): 1.049746982742775    (degrees): 60.146071667753475

cov:  [[1.00005    0.48973754]
 [0.48973754 1.00005   ]]
phase estimate (radians):  1.059007630672643 (degrees):  60.67666770969148

Hướng dẫn phase shift in python - chuyển pha trong python

Hướng dẫn phase shift in python - chuyển pha trong python

Phương pháp tương quan chéo

Đây là một đoạn mã để chứng minh làm thế nào nó có thể hoạt động.

from statsmodels.tsa.stattools import ccf
xc = ccf(data[:,0], data[:,1])
plt.figure()
angle = t * omega * 2 * math.pi

n = math.ceil(fs / omega)
plt.plot(angle[:n], xc[:n])
plt.show()
print(angle)

maxa = max(np.abs(xc[:int(n/2)]))
maxangle = angle[np.abs(xc)==maxa]
print('phase shift (radians): ',maxangle)

Output:

Hướng dẫn phase shift in python - chuyển pha trong python

phase shift (radians):  [2.3855998]

PCA

Câu trả lời ban đầu của tôi với PCA, nhưng nó phức tạp hơn. Bạn có thể chạy PCA trên các tín hiệu được tiêu chuẩn hóa, sau đó tỷ lệ các phương sai được giải thích sẽ chứa thông tin về sự khác biệt pha của các tín hiệu.