Wstep
Spis treści
⬆ Próbkowanie sygnałów analogowych
Sygnały zapisujemy, przetwarzamy i analizujemy w postaci ciągów liczb. Przejście od sygnału ciągłego do cyfrowego odbywa się przez proces próbkowania, czyli zapisywania kolejnych amplitud sygnału w ustalonych, stałych odstępach czasu, omawiany wcześniej na TIiK.
102, 195, 80, 16, 147, 178
Żeby odtworzyć fizyczne własności sygnału, czyli narysować zapisane wartości próbek w odpowiedniej skali, musimy znać częstość próbkowania i stałą kalibracji.
Wyrażana w hercach (Hz) częstość próbkowania (ang. sampling frequency, \(f_s\)) to liczba próbek na sekundę. Jest ona odwrotnością odstępu w czasie między kolejnymi próbkami (\(\Delta t\)):
\(f_s = \dfrac{1}{\Delta t}\)
Stała kalibracji to współczynnik, przez który mnożymy zapisane liczby, żeby otrzymać wartości w jednostkach fizycznych, na przykład mikrowoltach.
Oczywiście musimy też wiedzieć, w jakim formacie zapisano na dysku liczby (formaty omawialiśmy na wykładzie o binarnych reprezentacjach liczb), oraz, w przypadku sygnałów wielozmiennych o jednolitym próbkowaniu, znać liczbę kanałów. Taka dodatkowa informacja (metainformacja) jest konieczna do poprawnego wyświetlenia danych z pliku, w którym zapisano dane wielokanałowe, jak np. kilka odprowadzeń EEG lub dane kilku spółek giełdowych, próbkowane i zapisywane w jednakowych odstępach czasu.
| Informacje o częstości próbkowania, stałej kalibracji, liczbie i nazwach kanałów itp. to metainformacja, klucz do poprawnego odczytu i intepretacji zapisanych liczb. |
Zawartość pliku "wakeEEG.xml", zawierającego metainformację określającą sposób wyświetlania i opisu liczb zawartych w pliku "wakeEEG.bin" według formatu opracowanego na WF UW w programie Svarog:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<rs:rawSignal xmlns:rs="http://signalml.org/rawsignal">
<rs:exportFileName>moto128.bin</rs:exportFileName>
<rs:sourceFileName>durka_moto3.bin</rs:sourceFileName>
<rs:sourceFileFormat>
<rs:rawSignalInfo/>
</rs:sourceFileFormat>
<rs:samplingFrequency>128.0</rs:samplingFrequency>
<rs:channelCount>20</rs:channelCount>
<rs:sampleCount>20480</rs:sampleCount>
<rs:sampleType>FLOAT</rs:sampleType>
<rs:byteOrder>LITTLE_ENDIAN</rs:byteOrder>
<rs:pageSize>20.0</rs:pageSize>
<rs:blocksPerPage>1</rs:blocksPerPage>
<rs:eegSystemName>
<rs:eegSystemSymbol>EEG 10_20 Cap19</rs:eegSystemSymbol>
<rs:eegSystemType>adults</rs:eegSystemType>
</rs:eegSystemName>
<rs:channelLabels>
<rs:label>Fp1</rs:label>
<rs:label>Fp2</rs:label>
<rs:label>F7</rs:label>
<rs:label>F3</rs:label>
<rs:label>Fz</rs:label>
<rs:label>F4</rs:label>
<rs:label>F8</rs:label>
<rs:label>T7</rs:label>
<rs:label>C3</rs:label>
<rs:label>Cz</rs:label>
<rs:label>C4</rs:label>
<rs:label>T8</rs:label>
<rs:label>P7</rs:label>
<rs:label>P3</rs:label>
<rs:label>Pz</rs:label>
<rs:label>P4</rs:label>
<rs:label>P8</rs:label>
<rs:label>O1</rs:label>
<rs:label>O2</rs:label>
<rs:label>FCz</rs:label>
</rs:channelLabels>
<rs:exportDate>2013-03-20T12:59:21</rs:exportDate>
<rs:calibrationGain>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
<rs:calibrationParam>0.01</rs:calibrationParam>
</rs:calibrationGain>
<rs:calibrationOffset>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
<rs:calibrationParam>0.1</rs:calibrationParam>
</rs:calibrationOffset>
</rs:rawSignal>
|
Aliasing i częstość Nyquista
W procesie próbkowania kluczową rolę odgrywa twierdzenie o próbkowaniu (inaczej twierdzenie Nyquista-Shannona, czasem w skrócie twierdzenie Nyquista). Mówi ono, że sygnał ciągły możemy odtworzyć za zapisanych próbek, jeśli częstość próbkowania \(f_s\) była wyższa niż dwukrotność najwyższej z występujących w sygnale częstości \(f_{max}\), nazywana częstością Nyquista \(f_N\):
\( f_s = \dfrac{1}{\Delta t} \gt 2* f_{max} = f_N\)
Jeśli częstość próbkowania nie była wystarczająco wysoka, nie tylko stracimy informację o zmianach amplitudy sygnału "pomiędzy próbkami", ale dojdzie też do zafałszowania sygnału w niższych częstościach, które z pozoru nie powinny być zaburzone. Efekt ten jest bliżej omówiony w rozdziale Aliasing.
Sygnał dyskretny jako wektor
Skoro sygnał to po prostu ciąg liczb, możemy go potraktować jak wektor. Na płaszczyźnie wektor to para współrzędnych (x, y), w przestrzeni trójwymiarowej trójka liczby (x, y, z), które wyobrażamy sobie jako strzałkę wiodącą od punktu (0, 0, 0) do (x, y, z). Sygnał składający się z pięciu punktów będzie wektorem w przestrzeni pięciowymiarowej, więc intuicja "strzałki" dla większości z nas przestaje być użyteczna. Pomimo tego, możemy wciąż korzystać z użytecznych pojęć z dziedziny algebry wektorów, jak ortogonalność czy iloczyn skalarny.
Iloczyn skalarny
Iloczyn skalarny przyjmiemy jako miarę podobieństwa dwóch sygnałów. Obliczać go będziemy tak samo jak dla wektorów — przypomnijmy: niech \(\mathbf{x} = [x_1, x_2, x_3]\), i \(\mathbf{y} = [y_1, y_2, y_3]\); iloczyn skalarny tych wektorów oznaczamy \(\mathbf x \cdot \mathbf y\) (zarówno wytłuszczenie symboli wektorów, jak i symbol mnożenia/ilocznu skalarnego "\(\cdot\)", będziemy dalej pomijać):
\(\displaystyle \mathbf a \cdot \mathbf b = \sum_{i=1}^3 x_i y_i = x_1 y_1 + x_2 y_2 + x_3 y_3\)
A jak to będzie wyglądać dla sygnałów złożonych z więcej niż trzech punktów? Weźmy
\(x=[-2, -2, 2, -1, -2]\)
\(y=[-1, -1, 1, 1, 0]\)
Zamiast strzałek w pięciowymiarowej przestrzeni, łatwiej wizualizować na wykresach wartości kolejnych próbek:
\(x\cdot y = [-2, -2, 2, -1, -2] \cdot [-1, -1, 1, 1, 0] = 2+2+2-1+0 = 5\)
Ortogonalność
Kolejnym użytecznym pojęciem, które możemy zaczerpnąć bezpośrednio z algebry wektorów, jest ortogonalność. Dwa wektory (sygnały) są do siebie ortogonalne, jeśli ich iloczyn skalarny wynosi zero, jak poniżej:
W przypadku sygnału złożonego z 16 punktów, możemy ten fakt sprawdzić obliczając iloczyn skalarny punkt po punkcie, albo też zauważając prawidłowości występujące w każdym okresie górnego sygnału. W przypadku dłuższych i bardziej złożonych sygnałów może to już nie być takie oczywiste, jak np. ortogonalność wszystkich sinusów na poniższym rysunku, których częstości są całkowitymi wielokrotnościami częstości podstawowej:
| Zbiór ortogonalnych sinusów |
| \(f(x)=\sin(kx), k=1,2,\ldots\) |
Energia sygnału
Matematycznie energia sygnału \(x\) to \(\langle x,x \rangle\) (czyli \(x\cdot x\), iloczyn skalarny sygnału "z samym sobą"). Dla sygnałów ciągłych \(\langle x(t), x(t) \rangle = \int |x(t)|^2 dt\), dla sygnałów dyskretnych \( \langle x[n], x[n] \rangle = \sum_n |x[n]|^2\). Fizycznie musimy wziąć pod uwagę wspomniane wcześniej stałą kalibracji i częstość próbkowania:
- Jeśli sygnałem będzie prąd elektryczny o natężeniu \(i(t)\) mierzonym w amperach, płynący w obwodzie o oporności \(R\) omów, to wytracana przez niego energia wyniesie \(E_i = R \int |i(t)|^2 dt\) dżuli.
- W przypadku sygnału dyskretnego \(x[t]\), całkę \(\int x(t) dt \) zastępujemy sumą pól kolejnych prostokątów o wysokości \(x[n]\) i szerokości równej odstępowi między kolejnymi punktami \(\Delta t = \frac{1}{f_s}\)
- \(E_{x[n]} = \Delta t \sum_n |x(n)|^2 = \frac{1}{f_s} \sum_n |x(n)|^2 \)
Liczby zespolone
Przypomnijmy w skrócie: \(i^2=-1\). Liczbę zespoloną \(z\) możemy zapisać w postaci algebraicznej jako
- \(z=a+bi,\)
gdzie \(a\) to część rzeczywista, \(b\) — część urojona.
Sprzężenie zespolone liczby \(z\) oznaczamy \(\overline{z}\):
- \(\overline{z} = a - bi\)
a jej moduł to \(|z| = \sqrt{a^2 + b^2}\) (inaczej \(|z| = z \cdot \overline{z}\)).
Postać trygonometryczna:
- \(z = a + bi = |z| \cdot \dfrac{a}{|z|} + |z| \cdot \dfrac{b}{|z|}i = |z| \cdot (\cos \phi + i\sin \phi).\)
Wykorzystując wzór Eulera[1]
- \(e^{i\phi} = \cos(\phi) + i\sin(\phi)\)
możemy liczbę zespoloną zapisać jako
- \(z = |z|e^{i\phi}\)
Szereg Fouriera
Sygnał okresowy (o okresie \(T\)) można przedstawić w postaci szeregu Fouriera:
gdzie
| Dowód powyższego wzoru: |
| Mnożymy obie strony równania 1 przez \(e^\frac{2\pi i k t}{T}\)
i całkujemy po \(dt\) od \(0\) do \(T\): \( \int_0^T s(t) e^{{{2\pi i k t}\over{T}}} dt = \sum_{n=-\infty}^{+\infty} \int_0^T c_n e^{i{{2 \pi (k-n)}\over{T}} t}dt \) Całki po prawej stronie znikają dla \(k \ne n\). Jedyny niezerowy wyraz dla \(k = n\) wynosi \(\int_0^T c_n dt\), czyli \(c_n T\) (bo \(e^0=1\)). |
Każdą funkcję okresową możemy przedstawić w postaci sumy sinusów i kosinusów z odpowiednimi wagami — przypomnijmy: \(e^{i \phi} = \cos(\phi) + i \sin(\phi)\).
Wagi \(c_n\) możemy traktować jako względny udział odpowiadających im częstości.
Przykład: szereg Fouriera dla prostokąta
Policzmy postać współczynników Fouriera dla funkcji \(\Theta(t)\), określonej na przedziale \([0,1]\) w następujący sposób:
- \( \Theta(t) = \left\{ \begin{matrix} 1 &, & t \in [0, \frac{1}{2})\\ 0 &, & t \in [ \frac{1}{2}, 1] \end{matrix} \right. \)
| obliczenia: |
| Bezpośrednio z wzoru 2 dostajemy (dla \(T = 1\))
\(\begin{matrix}
c_{n} = \frac{1}{T}\int_{0}^{T} \Theta(t) e^\frac{i 2\pi n t}{T} d t
= \int_{0}^\frac{1}{2} e^{{{i 2\pi n t}}} d t = ( \mathrm{dla}\; n \ne 0 ) =
\left [\frac{1}{i 2\pi n} e^{{i 2\pi n t}} \right ]_{t=0}^{t=\frac{1}{2}} \\
= \frac{1}{i 2\pi n} ( e^{i \pi n} - 1 ) =
\left\{
\begin{matrix}
0 & \mathrm{dla}\; n = \pm2, \pm4, \ldots\\
i/\pi n & \mathrm{dla}\; n = \pm1, \pm3, \ldots
\end{matrix}
\right .\\
(\mathrm{dla}\; n=0) \;\; c_0 = \int_{0}^\frac{1}{2} 1 d t = \frac{1}{2}
\end{matrix}\)
Tak więc z wzoru 1 \(\begin{matrix} \Theta(t) = \sum_{-\infty}^{\infty} c_n e^{-i 2 \pi t n} = \frac{1}{2}\; + \sum_{n=\pm1, \pm3, \ldots} \frac{i}{\pi n} e^{-i 2 \pi t n}= \\ = \frac{1}{2}\; + \sum_{n=\pm1, \pm3, \ldots} \frac{i}{\pi n} \left( \cos(2\pi n t) - i \sin( 2\pi n t) \right)=\\ = \frac{1}{2}\; + \sum_{n=\pm1, \pm3, \ldots} \frac{i}{\pi n} \cos(2\pi n t)\;\; + \sum_{n=\pm1, \pm3, \ldots} \frac{1}{\pi n} \sin( 2\pi n t) \end{matrix}\)
|
Dostajemy
Od góry, kolejno:
funkcja \(\Theta\) (równanie 3) uzupełniona do funkcji okresowej, pierwszych 30 współczynników szeregu Fouriera,
kwadraty współczynników szeregu Fouriera — dyskretne widmo,
pierwszy wyraz rozwinięcia Fouriera, sumy pierwszych 10, 50, 500 i 5000 wyrazów rozwinięcia 4.
Jak widać, najtrudniejsza do wyrażenia z pomocą funkcji
trygonometrycznych jest nieciągłość funkcji \(\theta(t)\) w punktach \(\left\{\pm \frac{k}{2}, k \in N \right\}\); niejednorodna
zbieżność szeregów Fouriera w tych rejonach nosi nazwę efektu Gibbsa.
Przekształcenie Fouriera
Przejdźmy do nieskończoności z okresem sygnału: \(T\rightarrow\infty\). Wtedy odstęp \(\left(\frac{2\pi}{T}\right)\) między częstościami kolejnych elementów sumy szeregu Fouriera
\(\displaystyle s(t) =\sum_{n=-\infty}^{+\infty} c_n e^{-i\frac{2\pi t}{T} n}, \)
dąży do \(0\) i suma przechodzi w całkę
funkcja \(\hat{s}(f)\), zastępująca dyskretny ciąg współczynników szeregu Fouriera
\(\displaystyle c_{n} = \frac{1}{T}\int_{0}^{T} s(t) e^\frac{2\pi i n t}{T} d t \)
to transformata Fouriera sygnału \(s(t)\), czyli wynik działania przekształcenia (transformacji) Fouriera \(\mathcal{F}\).
- ↑ wzorem Eulera bywa również nazywane równanie \(e^{i\pi}+1=0\)