.
فرض کنید یک سیگنال شبیهسازی شده داریم شامل تتا (6Hz) + نویز سفید + نویز برق شهر 50Hz
ابتدا با اجرای کد زیر سیگنال پر از نویز را میبینیم.
سپس در ردیف دوم فقط باند تتا بعد از فیلتر شدن را میبینیم.
.
مثال عملی با پایتون (JupyterLab)
فرض کنید یک سیگنال شبیهسازی شده داریم شامل تتا (6Hz) + نویز سفید + نویز برق شهر 50Hz
ابتدا با اجرای کد زیر سیگنال پر از نویز را میبینیم.
سپس در ردیف دوم فقط باند تتا بعد از فیلتر شدن را میبینیم.
.
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import butter, filtfilt
# Sampling settings
fs = 500 # Sampling frequency (Hz)
t = np.linspace(0, 2, fs*2, endpoint=False) # 2 seconds duration
# Original signal: Theta oscillation (6 Hz)
theta = np.sin(2*np.pi*6*t)
# Noise components: random noise + 50Hz line noise
noise = 0.5 * np.random.randn(len(t))
line_noise = np.sin(2*np.pi*50*t)
lfp_raw = theta + noise + line_noise
# Define band-pass filter (to keep only 4-12 Hz)
def bandpass_filter(data, low, high, fs, order=4):
nyq = 0.5 * fs # Nyquist frequency
b, a = butter(order, [low/nyq, high/nyq], btype="band")
return filtfilt(b, a, data) # Apply filter forward & backward
# Apply filter to raw signal
lfp_filtered = bandpass_filter(lfp_raw, 4, 12, fs)
# Plotting
plt.figure(figsize=(12,6))
plt.subplot(2,1,1)
plt.plot(t, lfp_raw)
plt.title("Raw LFP (Theta + Noise)")
plt.ylabel("Amplitude")
plt.subplot(2,1,2)
plt.plot(t, lfp_filtered, color="red")
plt.title("Filtered LFP (Theta band 4-12Hz)")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.tight_layout()
plt.show()
import matplotlib.pyplot as plt
from scipy.signal import butter, filtfilt
# Sampling settings
fs = 500 # Sampling frequency (Hz)
t = np.linspace(0, 2, fs*2, endpoint=False) # 2 seconds duration
# Original signal: Theta oscillation (6 Hz)
theta = np.sin(2*np.pi*6*t)
# Noise components: random noise + 50Hz line noise
noise = 0.5 * np.random.randn(len(t))
line_noise = np.sin(2*np.pi*50*t)
lfp_raw = theta + noise + line_noise
# Define band-pass filter (to keep only 4-12 Hz)
def bandpass_filter(data, low, high, fs, order=4):
nyq = 0.5 * fs # Nyquist frequency
b, a = butter(order, [low/nyq, high/nyq], btype="band")
return filtfilt(b, a, data) # Apply filter forward & backward
# Apply filter to raw signal
lfp_filtered = bandpass_filter(lfp_raw, 4, 12, fs)
# Plotting
plt.figure(figsize=(12,6))
plt.subplot(2,1,1)
plt.plot(t, lfp_raw)
plt.title("Raw LFP (Theta + Noise)")
plt.ylabel("Amplitude")
plt.subplot(2,1,2)
plt.plot(t, lfp_filtered, color="red")
plt.title("Filtered LFP (Theta band 4-12Hz)")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.tight_layout()
plt.show()
❤2
.
کد زیر که سیگنالی شامل دو جزء است را اجرا کنید:
- یک موج اصلی 10 Hz (شبیه LFP واقعی)
- نویز برق 50 Hz
نتیجه اجرای کد در تصویر است.👆
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
# Sampling rate and time vector
fs = 1000 # Hz
t = np.linspace(0, 1, fs, endpoint=False)
# Create signal: 10 Hz + 50 Hz noise
clean = np.sin(2*np.pi*10*t)
line_noise = 0.5 * np.sin(2*np.pi*50*t)
noisy_signal = clean + line_noise
# Plot the noisy signal
plt.figure(figsize=(10,4))
plt.plot(t, noisy_signal, label="Noisy Signal")
plt.plot(t, clean, 'r--', label="Clean (10 Hz)")
plt.legend()
plt.title("Simulated LFP with 50 Hz Line Noise")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.tight_layout()
plt.show()
کد زیر که سیگنالی شامل دو جزء است را اجرا کنید:
- یک موج اصلی 10 Hz (شبیه LFP واقعی)
- نویز برق 50 Hz
نتیجه اجرای کد در تصویر است.👆
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
# Sampling rate and time vector
fs = 1000 # Hz
t = np.linspace(0, 1, fs, endpoint=False)
# Create signal: 10 Hz + 50 Hz noise
clean = np.sin(2*np.pi*10*t)
line_noise = 0.5 * np.sin(2*np.pi*50*t)
noisy_signal = clean + line_noise
# Plot the noisy signal
plt.figure(figsize=(10,4))
plt.plot(t, noisy_signal, label="Noisy Signal")
plt.plot(t, clean, 'r--', label="Clean (10 Hz)")
plt.legend()
plt.title("Simulated LFP with 50 Hz Line Noise")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.tight_layout()
plt.show()
.
نویز برق شهر
import numpy as np
import matplotlib.pyplot as plt
# --- Parameters ---
fs = 1000 # Sampling frequency (Hz)
t = np.linspace(0, 1, fs) # 1 second duration
f_power = 50 # Power line frequency (Hz)
amplitude = 1.0 # Amplitude
# --- Generate pure 50 Hz noise ---
power_noise = amplitude * np.sin(2 * np.pi * f_power * t)
# --- FFT (Frequency Spectrum) ---
freqs = np.fft.rfftfreq(len(t), 1/fs)
spectrum = np.abs(np.fft.rfft(power_noise)) / len(t)
# --- Plot ---
plt.figure(figsize=(12,5))
# Time domain
plt.subplot(1,2,1)
plt.plot(t, power_noise, color="red")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.title("50 Hz Power Line Noise (Time Domain)")
plt.xlim(0, 0.1) # zoom in to see cycles
# Frequency domain
plt.subplot(1,2,2)
plt.stem(freqs, spectrum, basefmt=" ")
plt.xlabel("Frequency (Hz)")
plt.ylabel("Amplitude")
plt.title("Frequency Spectrum (Peak at 50 Hz)")
plt.xlim(0, 100) # only show up to 100 Hz
plt.tight_layout()
plt.show()
نویز برق شهر
import numpy as np
import matplotlib.pyplot as plt
# --- Parameters ---
fs = 1000 # Sampling frequency (Hz)
t = np.linspace(0, 1, fs) # 1 second duration
f_power = 50 # Power line frequency (Hz)
amplitude = 1.0 # Amplitude
# --- Generate pure 50 Hz noise ---
power_noise = amplitude * np.sin(2 * np.pi * f_power * t)
# --- FFT (Frequency Spectrum) ---
freqs = np.fft.rfftfreq(len(t), 1/fs)
spectrum = np.abs(np.fft.rfft(power_noise)) / len(t)
# --- Plot ---
plt.figure(figsize=(12,5))
# Time domain
plt.subplot(1,2,1)
plt.plot(t, power_noise, color="red")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.title("50 Hz Power Line Noise (Time Domain)")
plt.xlim(0, 0.1) # zoom in to see cycles
# Frequency domain
plt.subplot(1,2,2)
plt.stem(freqs, spectrum, basefmt=" ")
plt.xlabel("Frequency (Hz)")
plt.ylabel("Amplitude")
plt.title("Frequency Spectrum (Peak at 50 Hz)")
plt.xlim(0, 100) # only show up to 100 Hz
plt.tight_layout()
plt.show()
.
نویز برق شهر
سمت چپ: در Time Domain محور افقی زمان است، سیگنال را به صورت تغییر دامنه برحسب زمان میبینیم.
در زمان موج سینوسی قرمز بالا و پایین میرود.
در فرکانس فقط یک پیک واضح در 50Hz ظاهر میشود.
سمت راست: در FFT Domain (Frequency Domain) با کمک Fast Fourier Transform (FFT) سیگنال را تجزیه میکنیم و میبینیم انرژی یا توان آن در چه فرکانسهایی متمرکز است.
.
نویز برق شهر
سمت چپ: در Time Domain محور افقی زمان است، سیگنال را به صورت تغییر دامنه برحسب زمان میبینیم.
در زمان موج سینوسی قرمز بالا و پایین میرود.
در فرکانس فقط یک پیک واضح در 50Hz ظاهر میشود.
سمت راست: در FFT Domain (Frequency Domain) با کمک Fast Fourier Transform (FFT) سیگنال را تجزیه میکنیم و میبینیم انرژی یا توان آن در چه فرکانسهایی متمرکز است.
.
.
سیگنالهای واقعی (مثل صدا یا EEG) پیوسته هستند.
برای پردازش با کامپیوتر باید آنها را به شکل گسسته (Discrete) ذخیره کنیم.
نرخ نمونهبرداری یا Sampling rate (fs) یعنی چند بار در ثانیه از سیگنال نمونهبرداری میکنیم.
مثلا fs = 100 Hz یعنی در هر ثانیه 100 نقطه از سیگنال برداشته میشود.
هرچقدر fs بیشتر باشد، سیگنال دقیقتر ذخیره میشود.
اگر fs کم باشد سیگنال "خوب دیده نمیشود.
.
مفهوم Sampling Rate (نرخ نمونهبرداری)
سیگنالهای واقعی (مثل صدا یا EEG) پیوسته هستند.
برای پردازش با کامپیوتر باید آنها را به شکل گسسته (Discrete) ذخیره کنیم.
نرخ نمونهبرداری یا Sampling rate (fs) یعنی چند بار در ثانیه از سیگنال نمونهبرداری میکنیم.
مثلا fs = 100 Hz یعنی در هر ثانیه 100 نقطه از سیگنال برداشته میشود.
هرچقدر fs بیشتر باشد، سیگنال دقیقتر ذخیره میشود.
اگر fs کم باشد سیگنال "خوب دیده نمیشود.
برای فهم دقیقتر این موضوع کد زیر را اجرا کنید. 👇
.
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
# Continuous signal (10 Hz sine wave)
f = 10 # frequency of signal (Hz)
t = np.linspace(0, 1, 1000, endpoint=False) # high resolution (1000 samples/sec)
signal = np.sin(2 * np.pi * f * t)
# Sampling rates
fs1 = 20 # low sampling rate (20 Hz)
fs2 = 100 # higher sampling rate (100 Hz)
t1 = np.linspace(0, 1, fs1, endpoint=False)
t2 = np.linspace(0, 1, fs2, endpoint=False)
signal1 = np.sin(2 * np.pi * f * t1)
signal2 = np.sin(2 * np.pi * f * t2)
# Interpolation to rebuild signals
interp1 = interp1d(t1, signal1, kind='cubic', fill_value="extrapolate")
interp2 = interp1d(t2, signal2, kind='cubic', fill_value="extrapolate")
reconstructed1 = interp1(t)
reconstructed2 = interp2(t)
# Plot in 3 separate subplots
plt.figure(figsize=(12,8))
# Original
plt.subplot(3,1,1)
plt.plot(t, signal, 'k-', linewidth=2, label="Original (1000 Hz)")
plt.title("Original Continuous Signal")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.legend()
plt.grid(True)
# fs = 20 Hz
plt.subplot(3,1,2)
plt.plot(t, reconstructed1, 'r-', linewidth=2, label="Reconstructed (20 Hz)")
plt.plot(t1, signal1, 'ro', markersize=6, label="Samples")
plt.title("Reconstructed Signal (20 Hz Sampling)")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.legend()
plt.grid(True)
# fs = 100 Hz
plt.subplot(3,1,3)
plt.plot(t, reconstructed2, 'g-', linewidth=2, label="Reconstructed (100 Hz)")
plt.plot(t2, signal2, 'gs', markersize=5, label="Samples")
plt.title("Reconstructed Signal (100 Hz Sampling)")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
# Continuous signal (10 Hz sine wave)
f = 10 # frequency of signal (Hz)
t = np.linspace(0, 1, 1000, endpoint=False) # high resolution (1000 samples/sec)
signal = np.sin(2 * np.pi * f * t)
# Sampling rates
fs1 = 20 # low sampling rate (20 Hz)
fs2 = 100 # higher sampling rate (100 Hz)
t1 = np.linspace(0, 1, fs1, endpoint=False)
t2 = np.linspace(0, 1, fs2, endpoint=False)
signal1 = np.sin(2 * np.pi * f * t1)
signal2 = np.sin(2 * np.pi * f * t2)
# Interpolation to rebuild signals
interp1 = interp1d(t1, signal1, kind='cubic', fill_value="extrapolate")
interp2 = interp1d(t2, signal2, kind='cubic', fill_value="extrapolate")
reconstructed1 = interp1(t)
reconstructed2 = interp2(t)
# Plot in 3 separate subplots
plt.figure(figsize=(12,8))
# Original
plt.subplot(3,1,1)
plt.plot(t, signal, 'k-', linewidth=2, label="Original (1000 Hz)")
plt.title("Original Continuous Signal")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.legend()
plt.grid(True)
# fs = 20 Hz
plt.subplot(3,1,2)
plt.plot(t, reconstructed1, 'r-', linewidth=2, label="Reconstructed (20 Hz)")
plt.plot(t1, signal1, 'ro', markersize=6, label="Samples")
plt.title("Reconstructed Signal (20 Hz Sampling)")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.legend()
plt.grid(True)
# fs = 100 Hz
plt.subplot(3,1,3)
plt.plot(t, reconstructed2, 'g-', linewidth=2, label="Reconstructed (100 Hz)")
plt.plot(t2, signal2, 'gs', markersize=5, label="Samples")
plt.title("Reconstructed Signal (100 Hz Sampling)")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
.
1- داده ثبت شده توسط خود یا همکارانتان را انتخاب کنید
2- داده مد نظر را ار دیتاستهای موجود دانلود کنید.
در جدول زیر برخی از دیتاستهای در دسترس معرفی میشوند و در ادامه به توضیح هر کدام پرداخته میشود.
در برخی از دیتاستها مجبور هستیم کل آن را دانلود کنیم.
به عبارت دیگر فایلها مستقل از هم آپلود نشدهاند.
1- از دیتاستهایی که فایلها جداگانه آپلود شدهاند استفاده کنیم (مانند شماره 2 جدول زیر *).
2- از دیتاستهایی استفاده کنیم که حجم کمی دارند یا تعداد نمونه آن پایین است (مانند شماره 3 و 7 جدول زیر *).
.
برای تمرین روی داده EEG
1- داده ثبت شده توسط خود یا همکارانتان را انتخاب کنید
2- داده مد نظر را ار دیتاستهای موجود دانلود کنید.
در جدول زیر برخی از دیتاستهای در دسترس معرفی میشوند و در ادامه به توضیح هر کدام پرداخته میشود.
در برخی از دیتاستها مجبور هستیم کل آن را دانلود کنیم.
به عبارت دیگر فایلها مستقل از هم آپلود نشدهاند.
اگر مایل نیستید حجم زیادی را دانلود کنید دو راه پیشنهاد میشود.
1- از دیتاستهایی که فایلها جداگانه آپلود شدهاند استفاده کنیم (مانند شماره 2 جدول زیر *).
2- از دیتاستهایی استفاده کنیم که حجم کمی دارند یا تعداد نمونه آن پایین است (مانند شماره 3 و 7 جدول زیر *).
.
.
نوع داده: ترکیبی از EEG و MEG
این دیتاست بهصورت پیشفرض همراه با کتابخانهی MNE-Python ارائه میشود.
برای آموزش و آزمایش روشهای پایه در تحلیل سیگنالهای مغزی طراحی شده است.
داده شامل پاسخهای شنوایی و بینایی (Auditory/Visual Evoked Responses) است که از یک فرد در حین دیدن و شنیدن محرکها ثبت شده است.
تعداد کانال: حدود ۳۰۰ کانال MEG و ۶۰ کانال EEG
فرمت: fif (استاندارد MNE)
برای آموزش مراحل preprocessing، فیلتر، epoching و ERP مناسب است.
https://mne.tools/stable/documentation/datasets.html
.
1. MNE Sample Dataset
نوع داده: ترکیبی از EEG و MEG
این دیتاست بهصورت پیشفرض همراه با کتابخانهی MNE-Python ارائه میشود.
برای آموزش و آزمایش روشهای پایه در تحلیل سیگنالهای مغزی طراحی شده است.
داده شامل پاسخهای شنوایی و بینایی (Auditory/Visual Evoked Responses) است که از یک فرد در حین دیدن و شنیدن محرکها ثبت شده است.
ویژگیها
تعداد کانال: حدود ۳۰۰ کانال MEG و ۶۰ کانال EEG
فرمت: fif (استاندارد MNE)
برای آموزش مراحل preprocessing، فیلتر، epoching و ERP مناسب است.
https://mne.tools/stable/documentation/datasets.html
.
.
نوع داده: EEG از سطح جمجمه
یکی از معروفترین دیتاستهای آزاد EEG است که شامل فعالیت مغزی در زمان انجام و تصور حرکت است.
برای آموزش الگوریتمهای BCI کاربرد دارد.
شامل فایل جدا برای هر فرد است. میتوان فقط یک یا چند فایل .edf خاص را انتخاب و دانلود کرد.
توسط دانشگاه کینگز کالج لندن تهیه شده است.
۱۰۹ شرکتکننده سالم
ثبت با سیستم ۶۴ کاناله
هر فرد چندین بار حرکات دستها و پاها را اجرا (واقعی یا خیالی)
دادهها بهصورت .edf، .mat و .csv در دسترس هستند.
کاربرد: تشخیص قصد حرکتی از EEG، یادگیری ماشین، فیلترگذاری و ویژگییابی.
https://physionet.org/content/eegmmidb/1.0.0
.
2. EEG Motor Movement / Imagery Dataset
نوع داده: EEG از سطح جمجمه
یکی از معروفترین دیتاستهای آزاد EEG است که شامل فعالیت مغزی در زمان انجام و تصور حرکت است.
برای آموزش الگوریتمهای BCI کاربرد دارد.
شامل فایل جدا برای هر فرد است. میتوان فقط یک یا چند فایل .edf خاص را انتخاب و دانلود کرد.
توسط دانشگاه کینگز کالج لندن تهیه شده است.
ویژگیها
۱۰۹ شرکتکننده سالم
ثبت با سیستم ۶۴ کاناله
هر فرد چندین بار حرکات دستها و پاها را اجرا (واقعی یا خیالی)
دادهها بهصورت .edf، .mat و .csv در دسترس هستند.
کاربرد: تشخیص قصد حرکتی از EEG، یادگیری ماشین، فیلترگذاری و ویژگییابی.
https://physionet.org/content/eegmmidb/1.0.0
.
.
نوع داده EEG: برای رقابتهای علمی BCI
مجموعه دادههای رسمی برای مسابقات بینالمللی BCI Competition IV دادهها از چندین شرکتکننده در حین انجام motor imagery جمعآوری شدهاند.
برای آموزش و تست الگوریتمهای طبقهبندی سیگنال EEG بسیار ارزشمند هستند.
اگر نمیخواهید دیتاست سنگین دانلود کنید، این مورد گزینه خوبی است.
۹ تا ۱۰ شرکتکننده
ثبت با ۲۲ تا ۶۴ کانال
نرخ نمونهبرداری ۲۵۰ تا ۱۰۰۰ هرتز
فرمتها edf و gdf
کاربرد
آموزش مدلهای یادگیری عمیق برای تشخیص نیت حرکتی از EEG
https://www.bbci.de/competition/iv/
.
3. BCI Competition IV
نوع داده EEG: برای رقابتهای علمی BCI
مجموعه دادههای رسمی برای مسابقات بینالمللی BCI Competition IV دادهها از چندین شرکتکننده در حین انجام motor imagery جمعآوری شدهاند.
برای آموزش و تست الگوریتمهای طبقهبندی سیگنال EEG بسیار ارزشمند هستند.
اگر نمیخواهید دیتاست سنگین دانلود کنید، این مورد گزینه خوبی است.
ویژگیها
۹ تا ۱۰ شرکتکننده
ثبت با ۲۲ تا ۶۴ کانال
نرخ نمونهبرداری ۲۵۰ تا ۱۰۰۰ هرتز
فرمتها edf و gdf
کاربرد
آموزش مدلهای یادگیری عمیق برای تشخیص نیت حرکتی از EEG
https://www.bbci.de/competition/iv/
.