Amaliyot ā Kompleks Sonlar va Furye
Python yordamida signal tahlili va filtrlash.
Loyiha: Sensor Signalini Filtrlashā
Maqsadā
IMU sensoridan kelayotgan shovqinli signalni tahlil qilish va tozalash.
1-Qism: Muhitni Sozlashā
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
from scipy.fft import fft, fftfreq, ifft
# Grafika sozlamalari
plt.rcParams['figure.figsize'] = (12, 6)
plt.rcParams['font.size'] = 11
plt.rcParams['axes.grid'] = True
2-Qism: Kompleks Sonlar bilan Ishlashā
Asosiy Operatsiyalarā
# Kompleks son yaratish
z1 = 3 + 4j
z2 = complex(1, -2)
print(f"z1 = {z1}")
print(f"z2 = {z2}")
print(f"z1 + z2 = {z1 + z2}")
print(f"z1 * z2 = {z1 * z2}")
print(f"|z1| = {abs(z1)}")
print(f"arg(z1) = {np.angle(z1)} rad = {np.degrees(np.angle(z1))}°")
print(f"conj(z1) = {np.conj(z1)}")
Eksponensial Ko'rinishā
# Euler formulasi
theta = np.pi / 4 # 45 daraja
z = np.exp(1j * theta)
print(f"e^(i*pi/4) = {z}")
print(f"= {z.real:.4f} + {z.imag:.4f}i")
print(f"= cos(45°) + i*sin(45°) = {np.cos(theta):.4f} + {np.sin(theta):.4f}i")
Kompleks Tekislikda Vizualizatsiyaā
def plot_complex(z_list, labels=None):
"""Kompleks sonlarni tekislikda chizish."""
plt.figure(figsize=(8, 8))
for i, z in enumerate(z_list):
label = labels[i] if labels else f'z{i+1}'
plt.arrow(0, 0, z.real, z.imag, head_width=0.1,
head_length=0.1, fc='blue', ec='blue')
plt.plot(z.real, z.imag, 'ro', markersize=10)
plt.annotate(label, (z.real, z.imag), fontsize=12,
xytext=(5, 5), textcoords='offset points')
plt.axhline(y=0, color='k', linewidth=0.5)
plt.axvline(x=0, color='k', linewidth=0.5)
plt.xlabel('Real')
plt.ylabel('Imaginary')
plt.title('Kompleks Tekislik')
plt.axis('equal')
plt.grid(True)
plt.show()
# Misol
z_list = [3+4j, -2+1j, 1-3j, 2*np.exp(1j*np.pi/3)]
plot_complex(z_list, ['3+4i', '-2+i', '1-3i', '2e^(iĻ/3)'])
3-Qism: Furye Qatoriā
To'rtburchak To'lqin Sinteziā
def square_wave_fourier(t, n_terms):
"""To'rtburchak to'lqinni Furye qatori bilan yaratish."""
result = np.zeros_like(t)
for n in range(1, n_terms + 1, 2): # faqat toq sonlar
result += (4 / (n * np.pi)) * np.sin(n * t)
return result
# Vaqt o'qi
t = np.linspace(0, 4*np.pi, 1000)
# Turli sondagi harmonikalar
plt.figure(figsize=(14, 8))
for i, n_terms in enumerate([1, 3, 5, 15, 51]):
plt.subplot(2, 3, i+1)
y = square_wave_fourier(t, n_terms)
plt.plot(t, y, 'b-', linewidth=1.5)
plt.title(f'{n_terms} garmonika')
plt.ylim([-1.5, 1.5])
plt.xlabel('t')
plt.ylabel('f(t)')
# Ideal to'rtburchak
plt.subplot(2, 3, 6)
ideal = np.sign(np.sin(t))
plt.plot(t, ideal, 'r-', linewidth=1.5)
plt.title('Ideal to\'rtburchak')
plt.ylim([-1.5, 1.5])
plt.xlabel('t')
plt.ylabel('f(t)')
plt.tight_layout()
plt.savefig('fourier_square_wave.png', dpi=150)
plt.show()
Gibbs Effektiā
# Furye qatori keskin o'tish joylarida "o'sib" ketadi
t = np.linspace(-0.1, 0.1, 1000) + np.pi # kesish nuqtasi atrofida
plt.figure(figsize=(12, 5))
for n_terms in [10, 50, 200]:
y = square_wave_fourier(t, n_terms)
plt.plot(t - np.pi, y, label=f'N = {n_terms}')
plt.axhline(y=1, color='r', linestyle='--', alpha=0.5)
plt.axhline(y=-1, color='r', linestyle='--', alpha=0.5)
plt.xlabel('t')
plt.ylabel('f(t)')
plt.title('Gibbs Effekti (kesish nuqtasida ~9% oshib ketish)')
plt.legend()
plt.savefig('gibbs_effect.png', dpi=150)
plt.show()
4-Qism: FFT ā Spektral Tahlilā
Signal Yaratish va FFTā
# Signal parametrlari
fs = 1000 # Namunalash chastotasi (Hz)
T = 1.0 # Davomiylik (s)
N = int(fs * T) # Namunalar soni
t = np.linspace(0, T, N, endpoint=False)
# Signal: 50 Hz va 120 Hz komponentlar + shovqin
f1, f2 = 50, 120
signal_clean = np.sin(2*np.pi*f1*t) + 0.5*np.sin(2*np.pi*f2*t)
noise = 0.3 * np.random.randn(N)
signal_noisy = signal_clean + noise
# FFT
fft_result = fft(signal_noisy)
frequencies = fftfreq(N, 1/fs)
# Faqat musbat chastotalar
pos_mask = frequencies >= 0
freqs_pos = frequencies[pos_mask]
fft_pos = np.abs(fft_result[pos_mask]) * 2 / N # Normalizatsiya
# Vizualizatsiya
fig, axs = plt.subplots(2, 1, figsize=(14, 8))
axs[0].plot(t[:200], signal_noisy[:200], 'b-', alpha=0.7, label='Shovqinli')
axs[0].plot(t[:200], signal_clean[:200], 'r-', linewidth=2, label='Toza')
axs[0].set_xlabel('Vaqt (s)')
axs[0].set_ylabel('Amplituda')
axs[0].set_title('Vaqt Sohasi')
axs[0].legend()
axs[1].stem(freqs_pos[:150], fft_pos[:150], 'b', markerfmt='bo', basefmt=' ')
axs[1].set_xlabel('Chastota (Hz)')
axs[1].set_ylabel('Amplituda')
axs[1].set_title('Chastota Sohasi (FFT)')
axs[1].axvline(x=50, color='r', linestyle='--', alpha=0.5, label='50 Hz')
axs[1].axvline(x=120, color='g', linestyle='--', alpha=0.5, label='120 Hz')
axs[1].legend()
plt.tight_layout()
plt.savefig('fft_analysis.png', dpi=150)
plt.show()
Spektrogram (Vaqt-Chastota Tahlili)ā
# Chirp signal (chastota oshib boradi)
t_chirp = np.linspace(0, 2, 2000)
chirp_signal = signal.chirp(t_chirp, f0=10, f1=200, t1=2, method='linear')
# Spektrogram
f, t_spec, Sxx = signal.spectrogram(chirp_signal, fs=1000, nperseg=128)
plt.figure(figsize=(12, 5))
plt.pcolormesh(t_spec, f, 10*np.log10(Sxx), shading='gouraud', cmap='viridis')
plt.ylabel('Chastota (Hz)')
plt.xlabel('Vaqt (s)')
plt.title('Spektrogram (Chirp Signal)')
plt.colorbar(label='Quvvat (dB)')
plt.savefig('spectrogram.png', dpi=150)
plt.show()
5-Qism: Raqamli Filtrlarā
Past Chastotali Filtr (Butterworth)ā
def butter_lowpass_filter(data, cutoff, fs, order=5):
"""Butterworth past chastotali filtr."""
nyq = 0.5 * fs
normal_cutoff = cutoff / nyq
b, a = signal.butter(order, normal_cutoff, btype='low', analog=False)
y = signal.filtfilt(b, a, data)
return y
# Filtr qo'llash
cutoff_freq = 80 # Hz
filtered_signal = butter_lowpass_filter(signal_noisy, cutoff_freq, fs)
# Natijalarni solishtirish
fig, axs = plt.subplots(3, 1, figsize=(14, 10))
# Vaqt sohasi
axs[0].plot(t[:300], signal_noisy[:300], 'b-', alpha=0.5, label='Shovqinli')
axs[0].plot(t[:300], filtered_signal[:300], 'r-', linewidth=2, label='Filtrlangan')
axs[0].plot(t[:300], signal_clean[:300], 'g--', linewidth=1, label='Original')
axs[0].set_xlabel('Vaqt (s)')
axs[0].set_ylabel('Amplituda')
axs[0].set_title(f'Past Chastotali Filtr (fc = {cutoff_freq} Hz)')
axs[0].legend()
# Filtrlangan signal spektri
fft_filtered = fft(filtered_signal)
fft_filt_pos = np.abs(fft_filtered[pos_mask]) * 2 / N
axs[1].stem(freqs_pos[:150], fft_pos[:150], 'b', markerfmt='bo',
basefmt=' ', label='Filtrlanmagan')
axs[1].stem(freqs_pos[:150], fft_filt_pos[:150], 'r', markerfmt='ro',
basefmt=' ', label='Filtrlangan')
axs[1].axvline(x=cutoff_freq, color='k', linestyle='--', label=f'Kesish: {cutoff_freq} Hz')
axs[1].set_xlabel('Chastota (Hz)')
axs[1].set_ylabel('Amplituda')
axs[1].set_title('Spektr Taqqoslash')
axs[1].legend()
# Filtr chastota javobi
w, h = signal.freqz(*signal.butter(5, cutoff_freq/(fs/2), 'low'))
axs[2].plot(w * fs / (2*np.pi), 20*np.log10(abs(h)), 'b-', linewidth=2)
axs[2].axvline(x=cutoff_freq, color='r', linestyle='--')
axs[2].axhline(y=-3, color='g', linestyle='--', label='-3 dB')
axs[2].set_xlabel('Chastota (Hz)')
axs[2].set_ylabel('Amplituda (dB)')
axs[2].set_title('Filtr Chastota Javobi')
axs[2].set_xlim([0, 200])
axs[2].set_ylim([-60, 5])
axs[2].legend()
plt.tight_layout()
plt.savefig('lowpass_filter.png', dpi=150)
plt.show()
Band-Stop Filtr (Notch)ā
def notch_filter(data, freq, fs, Q=30):
"""Notch filtr - ma'lum chastotani yo'qotish."""
nyq = 0.5 * fs
w0 = freq / nyq
b, a = signal.iirnotch(w0, Q)
y = signal.filtfilt(b, a, data)
return y
# 120 Hz komponentni yo'qotish
notch_filtered = notch_filter(signal_noisy, 120, fs)
plt.figure(figsize=(14, 5))
plt.subplot(1, 2, 1)
plt.plot(t[:300], signal_noisy[:300], 'b-', alpha=0.5, label='Original')
plt.plot(t[:300], notch_filtered[:300], 'r-', linewidth=2, label='Notch 120 Hz')
plt.xlabel('Vaqt (s)')
plt.ylabel('Amplituda')
plt.title('Notch Filtr Natijasi')
plt.legend()
plt.subplot(1, 2, 2)
fft_notch = fft(notch_filtered)
fft_notch_pos = np.abs(fft_notch[pos_mask]) * 2 / N
plt.stem(freqs_pos[:150], fft_pos[:150], 'b', markerfmt='bo', basefmt=' ', label='Original')
plt.stem(freqs_pos[:150], fft_notch_pos[:150], 'r', markerfmt='ro', basefmt=' ', label='Notch')
plt.xlabel('Chastota (Hz)')
plt.ylabel('Amplituda')
plt.title('Spektr')
plt.legend()
plt.tight_layout()
plt.savefig('notch_filter.png', dpi=150)
plt.show()
6-Qism: IMU Sensor Simulyatsiyasiā
Shovqinli Akselerometr Ma'lumotlariā
# IMU ma'lumotlarini simulyatsiya qilish
duration = 5 # sekund
fs_imu = 200 # Hz (odatiy IMU chastotasi)
t_imu = np.linspace(0, duration, duration * fs_imu)
# "Real" harakat (past chastotali)
motion = 0.5 * np.sin(2*np.pi*0.5*t_imu) # 0.5 Hz - odam yurishi
motion += 0.3 * np.sin(2*np.pi*2*t_imu) # 2 Hz - qadamlar
# Gravitatsiya
gravity = 9.81
# Shovqin (yuqori chastotali)
vibration = 0.2 * np.sin(2*np.pi*50*t_imu) # 50 Hz motor tebranishi
noise = 0.1 * np.random.randn(len(t_imu)) # tasodifiy shovqin
# To'liq akselerometr signali
accel_raw = gravity + motion + vibration + noise
# Filtrlash
accel_filtered = butter_lowpass_filter(accel_raw, 10, fs_imu, order=4)
# Vizualizatsiya
fig, axs = plt.subplots(2, 2, figsize=(14, 10))
# Vaqt sohasi
axs[0, 0].plot(t_imu, accel_raw, 'b-', alpha=0.5, linewidth=0.5, label='Raw')
axs[0, 0].plot(t_imu, accel_filtered, 'r-', linewidth=2, label='Filtrlangan')
axs[0, 0].plot(t_imu, gravity + motion, 'g--', linewidth=1, label='Ideal')
axs[0, 0].set_xlabel('Vaqt (s)')
axs[0, 0].set_ylabel('Tezlanish (m/s²)')
axs[0, 0].set_title('Akselerometr Ma\'lumotlari')
axs[0, 0].legend()
# Qisqa muddat
axs[0, 1].plot(t_imu[:100], accel_raw[:100], 'b-', alpha=0.5, label='Raw')
axs[0, 1].plot(t_imu[:100], accel_filtered[:100], 'r-', linewidth=2, label='Filtrlangan')
axs[0, 1].set_xlabel('Vaqt (s)')
axs[0, 1].set_ylabel('Tezlanish (m/s²)')
axs[0, 1].set_title('Yaqindan Ko\'rinish (0.5 s)')
axs[0, 1].legend()
# Raw spektr
fft_raw = fft(accel_raw - np.mean(accel_raw))
freqs_imu = fftfreq(len(accel_raw), 1/fs_imu)
pos_imu = freqs_imu >= 0
axs[1, 0].semilogy(freqs_imu[pos_imu], np.abs(fft_raw[pos_imu]), 'b-')
axs[1, 0].axvline(x=10, color='r', linestyle='--', label='Filtr kesishi')
axs[1, 0].set_xlabel('Chastota (Hz)')
axs[1, 0].set_ylabel('Amplituda (log)')
axs[1, 0].set_title('Raw Signal Spektri')
axs[1, 0].set_xlim([0, 100])
axs[1, 0].legend()
# Filtrlangan spektr
fft_filt = fft(accel_filtered - np.mean(accel_filtered))
axs[1, 1].semilogy(freqs_imu[pos_imu], np.abs(fft_filt[pos_imu]), 'r-')
axs[1, 1].axvline(x=10, color='r', linestyle='--', label='Filtr kesishi')
axs[1, 1].set_xlabel('Chastota (Hz)')
axs[1, 1].set_ylabel('Amplituda (log)')
axs[1, 1].set_title('Filtrlangan Signal Spektri')
axs[1, 1].set_xlim([0, 100])
axs[1, 1].legend()
plt.tight_layout()
plt.savefig('imu_filtering.png', dpi=150)
plt.show()
# Xatolik hisoblash
error_raw = np.std(accel_raw - (gravity + motion))
error_filtered = np.std(accel_filtered - (gravity + motion))
print(f"Raw signal xatoligi (std): {error_raw:.4f} m/s²")
print(f"Filtrlangan xatolik (std): {error_filtered:.4f} m/s²")
print(f"Yaxshilanish: {(1 - error_filtered/error_raw)*100:.1f}%")
7-Qism: Topshiriqlarā
Topshiriq 1: Kompleks Sonlarā
- ni hisoblang (Python va qo'lda)
- tenglamasining barcha ildizlarini toping
- Natijalarni kompleks tekislikda chizing
Topshiriq 2: Furye Tahliliā
- Uchburchak to'lqinning Furye qatorini yozing
- 10 ta garmonika bilan sintez qiling
- To'rtburchak to'lqin bilan taqqoslang
Topshiriq 3: Real Signal Tahliliā
- Audio fayl yuklang (
scipy.io.wavfile) - FFT orqali chastota spektrini tahlil qiling
- Shovqinli chastotalarni aniqlang va filtr qo'llang
Topshiriq 4: Dron Propeller Tahliliā
- Propeller tebranish signalini simulyatsiya qiling (RPM = 6000)
- Asosiy chastota va garmonikalarni spektrda ko'rsating
- Filtr qo'llab, asosiy tebranishni ajratib oling
Xulosaā
Bu amaliyotda:
- Kompleks sonlar bilan ishlashni o'rgandik
- Furye qatori va FFT ni qo'lladik
- Turli xil raqamli filtrlarni loyihalashtirdik
- IMU sensor ma'lumotlarini filtrladik
Keyingi qadam: Fizika bo'limida tebranishlar va to'lqinlar mavzusida ushbu bilimlarni qo'llash.