Esercizio - laboratorio 4, segnali continui aperiodici e risoluzione
In questa pagina 6
Testo (laboratorio 4 del corso Teoria dei Segnali, UniPD, file lab4.m parte 14 e parte14_variazioni.m). Un impulso rettangolare continuo di ampiezza V e semidurata s, per , viene campionato su con punti, passo . Calcolarne la trasformata con la FFT, con riordino delle due metà, e confrontarla con . Discutere come e cambiano il passo in frequenza e l'estensione dell'asse , nei tre casi ; ; , e dire quando compare aliasing.
Teoria usata: Trasformata di FourierLa trasformata di Fourier $S(f)=\int s(t)e^{-i2\pi ft}dt$ associa a un segnale continuo (anche aperiodico) la sua rappresentazione in frequenza; l'antitrasformata $s(t)=\int S(f)e^{i2\pi ft}df$ lo ricostruisce, perché gli esponenziali $e^{i2\pi ft}$ sono ortogonali su tutto $\mathbb R$ ($\int e^{i2\pi ft}dt=\delta(f)$). Per un segnale reale $S(-f)=S^*(f)$. Si calcola per i segnali notevoli (rect $\leftrightarrow$ sinc, $e^{-\alpha t}\mathbf 1(t)\leftrightarrow\frac1{\alpha+i2\pi f}$, gaussiana, $\delta\leftrightarrow1$, $1\leftrightarrow\delta$, gradino) e per i segnali periodici, la cui trasformata è un treno di impulsi di area $S_n$ in $nF$.Trasformata di Fourier →, Campionamento e ricostruzioneIl campionamento $s_c(nT)=s(nT)$ trasforma un segnale continuo in uno discreto e, in frequenza, ripete lo spettro con periodo $F_c=1/T$: $S_c(f)=\sum_kS(f-kF_c)$. Se le repliche si sovrappongono si ha aliasing e il segnale non è recuperabile. Un interpolatore $\mathbb Z(T)\to\mathbb R$ con risposta impulsiva $g$ produce $\tilde s(t)=\sum_nT g(t-nT)s(nT)$ e $\tilde S=G,S_c$. Teorema del campionamento: se $s$ ha banda $B$ e $F_c\ge2B$, l'interpolatore ideale $G=\operatorname{rect}(f/F_c)$ ricostruisce esattamente $s(t)=\sum s(nT)\operatorname{sinc}(F_c(t-nT))$. Se le ipotesi non valgono c'è un errore, in banda e fuori banda, riducibile con un prefiltro anti-aliasing.Campionamento e ricostruzione →, Trasformata di Fourier discreta (DFT) e FFTUn segnale discreto periodico di periodo $NT$ ha una trasformata discreta e periodica, la DFT: $S(kF)=\sum_{n=0}^{N-1}T,s(nT)e^{-i2\pi kn/N}$, con $F=1/(NT)$, e $s(nT)=\sum_{k=0}^{N-1}F,S(kF)e^{i2\pi kn/N}$. Dipende da soli $N$ numeri, si calcola senza approssimazioni e con la FFT costa $N\log_2N$ invece di $N^2$. I coefficienti di Fourier del segnale periodico sono $S_k=F,S(kF)$. La DFT dà anche campioni della trasformata di un segnale discreto o continuo a durata limitata (con zero-padding), ma la scalatura $T$ e l'asse delle frequenze vanno gestiti con cura.Trasformata di Fourier discreta (DFT) e FFT →, Segnali notevoli - gradino, rect, tri, sinc ed esponenzialiI segnali di uso più frequente sono la costante, la sinusoide $A_0\cos(2\pi f_0t+\varphi_0)$ e l'esponenziale complesso $Ae^{i2\pi f_0t}$ (periodici, a potenza finita), il gradino $\mathbf 1(t)$ e il segno, e gli impulsi a energia finita: $\operatorname{rect}$ (area $D$), $\operatorname{tri}$, $\operatorname{sinc}$ (area $1$), la gaussiana $e^{-\pi t^2}$ e gli esponenziali smorzati. Per ciascuno si sanno a memoria forma, area ed energia; gli altri segnali si ottengono da questi con traslazioni, scalature, somme e differenze.Segnali notevoli - gradino, rect, tri, sinc ed esponenziali →, Proprietà della trasformata di FourierLe regole della trasformata di Fourier trasformano operazioni sui segnali in operazioni sulle trasformate: linearità, ribaltamento, coniugio, traslazione nel tempo ($\times e^{-i2\pi ft_0}$) e in frequenza, convoluzione $\leftrightarrow$ prodotto, cambio di scala $s(at)\to\frac1{|a|}S(f/a)$, derivazione ($\times i2\pi f$), integrazione, regola di simmetria ($S(t)\to s(-f)$). Area $S(0)=\int s$, teorema di Parseval $\int|s|^2=\int|S|^2$. Durata e banda sono inversamente legati e un segnale non può avere durata e banda entrambe limitate; la banda del prodotto è la somma delle bande. Con queste regole si ricavano quasi tutte le trasformate senza integrare.Proprietà della trasformata di Fourier → (traslazione nel tempo e fase).
Cosa si vuole calcolare e perché
La trasformata di un segnale continuo non periodico è (Trasformata di FourierLa trasformata di Fourier $S(f)=\int s(t)e^{-i2\pi ft}dt$ associa a un segnale continuo (anche aperiodico) la sua rappresentazione in frequenza; l'antitrasformata $s(t)=\int S(f)e^{i2\pi ft}df$ lo ricostruisce, perché gli esponenziali $e^{i2\pi ft}$ sono ortogonali su tutto $\mathbb R$ ($\int e^{i2\pi ft}dt=\delta(f)$). Per un segnale reale $S(-f)=S^*(f)$. Si calcola per i segnali notevoli (rect $\leftrightarrow$ sinc, $e^{-\alpha t}\mathbf 1(t)\leftrightarrow\frac1{\alpha+i2\pi f}$, gaussiana, $\delta\leftrightarrow1$, $1\leftrightarrow\delta$, gradino) e per i segnali periodici, la cui trasformata è un treno di impulsi di area $S_n$ in $nF$.Trasformata di Fourier →). Un calcolatore ha solo campioni , quindi calcola la somma di Riemann in un numero finito di frequenze . La FFT dà esattamente questa somma per , con due precisazioni:
- il fattore è lo stesso del di (laboratorio 4, parti 1-8): ogni campione pesa ;
- la FFT vuole che il primo elemento sia l'istante , perciò il vettore (che parte da ) va riordinato: i campioni da in poi vanno davanti, quelli dei tempi negativi dietro (per la periodicità, sono equivalenti ai tempi ).
Le due domande del laboratorio sono: quanto fitta è la griglia in frequenza (la risoluzione) e fin dove arriva (l'estensione dell'asse), e come dipendono da e .
Parte 14 - il caso ,
import numpy as np
import matplotlib.pyplot as plt
# PARTE 14 - rect continuo (ampiezza A = 2, semi-durata T2 = 5 s) campionato su [-T1, T1) con N punti
N = 1000
T1 = 70
dt = 2 * T1 / N # passo di campionamento: durata totale 2 T1 divisa per N
t = np.arange(N) * dt - T1 # istanti da -T1 a T1 - dt
A = 2
T2 = 5
s = A * (np.abs(t) <= T2) # il rect: A dove |t| <= T2
plt.figure(figsize=(10, 6))
plt.subplot(2, 2, 1)
plt.plot(t, s)
plt.xlabel('Tempo [s]'); plt.ylim(-0.5, A + 0.5); plt.grid(True)
# trasformata analitica S(f) = 2 A T2 sinc(2 T2 f)
fa = np.linspace(-3, 3, 6001) # MATLAB [-3:0.001:3]
Sa = A * 2 * T2 * np.sinc(fa * (2 * T2))
plt.subplot(2, 2, 4)
plt.plot(fa, np.real(Sa), color='blue', label='Parte reale')
plt.plot(fa, np.imag(Sa), color='red', label='Parte immaginaria')
plt.grid(True); plt.xlabel('Frequenza [Hz]'); plt.xlim(-3, 3); plt.legend()
# trasformata numerica: il tempo 0 deve stare al primo posto del vettore
s = np.concatenate((s[N // 2:], s[:N // 2])) # MATLAB [s(N/2+1:N), s(1:N/2)]
df = 1 / (N * dt) # passo in frequenza: 1 / durata totale
f = np.arange(-N // 2, N // 2) * df # asse centrato: da -N/2 df a (N/2 - 1) df
S = dt * np.fft.fft(s) # il fattore dt e' la scalatura "area" della trasformata di un segnale continuo
S = np.concatenate((S[N // 2:], S[:N // 2])) # riordino: frequenze negative a sinistra
plt.subplot(2, 2, 2)
plt.plot(f, np.real(S), color='blue', label='Parte reale')
plt.plot(f, np.imag(S), color='red', label='Parte immaginaria')
plt.grid(True); plt.xlabel('Frequenza [Hz]'); plt.xlim(-3, 3); plt.legend()
plt.show()
campioni_rect = int(np.sum(np.abs(t) <= T2))
print(f"dt = {dt:.3f} s, df = 1/(N dt) = 1/(2 T1) = {df:.5f} Hz, asse da {f[0]:.3f} a {f[-1]:.3f} Hz (= +-1/(2 dt) = {1 / (2 * dt):.3f})")
print(f"campioni a 2: {campioni_rect} (larghezza numerica {campioni_rect * dt:.3f} s contro 2 T2 = {2 * T2} s)")
print(f"S(0) numerico = {S[N // 2].real:.4f} (= dt * somma = A * larghezza numerica); S(0) teorico = 2 A T2 = {2 * A * T2}")
sel = np.abs(f) <= 3
print(f"errore massimo |S - Sa| per |f| <= 3: {np.max(np.abs(S[sel] - A * 2 * T2 * np.sinc(f[sel] * 2 * T2))):.4f}")
print(f"parte immaginaria massima: {np.max(np.abs(S.imag)):.1e} (il rect e' pari: la trasformata e' reale)")Risultato:
dt = 0.140 s, df = 1/(N dt) = 1/(2 T1) = 0.00714 Hz, asse da -3.571 a 3.564 Hz (= +-1/(2 dt) = 3.571)
campioni a 2: 71 (larghezza numerica 9.940 s contro 2 T2 = 10 s)
S(0) numerico = 19.8800 (= dt * somma = A * larghezza numerica); S(0) teorico = 2 A T2 = 20
errore massimo |S - Sa| per |f| <= 3: 0.1579
parte immaginaria massima: 1.3e-15 (il rect e' pari: la trasformata e' reale)La trasformata analitica. (un rect di larghezza e altezza , Segnali notevoli - gradino, rect, tri, sinc ed esponenzialiI segnali di uso più frequente sono la costante, la sinusoide $A_0\cos(2\pi f_0t+\varphi_0)$ e l'esponenziale complesso $Ae^{i2\pi f_0t}$ (periodici, a potenza finita), il gradino $\mathbf 1(t)$ e il segno, e gli impulsi a energia finita: $\operatorname{rect}$ (area $D$), $\operatorname{tri}$, $\operatorname{sinc}$ (area $1$), la gaussiana $e^{-\pi t^2}$ e gli esponenziali smorzati. Per ciascuno si sanno a memoria forma, area ed energia; gli altri segnali si ottengono da questi con traslazioni, scalature, somme e differenze.Segnali notevoli - gradino, rect, tri, sinc ed esponenziali →) ha trasformata : reale e pari, (l'area ), zeri nei multipli di Hz, decadimento delle code. La parte immaginaria è nulla (segnale pari).
Grafico interattivo: Trasformata del rect di ampiezza 2 e semidurata 5: S(f) = 20 sinc(10 f), reale e pari, con S(0) = 20 (l'area), lobo principale tra ±0,1 Hz e zeri nei multipli di 0,1 Hz
Il campionamento e l'asse dei tempi. Con e il passo è s; va da a . I campioni con sono (i campioni sono nei punti e non ne è uno), quindi la larghezza numerica del rect è s e non s: la FFT vede un rect leggermente più stretto, con area . Questa è la causa del invece di . È un effetto del campionamento dei bordi, non della FFT.
Il riordino e gli assi. s = concatenate((s[N//2:], s[:N//2])) mette in testa l'elemento di indice , che è l'istante . La FFT restituisce le frequenze nell'ordine : si riordina anche S e si costruisce f = np.arange(-N//2, N//2) * df con
L'asse va da Hz a Hz, cioè . Il risultato è reale (parte immaginaria ) e riproduce con un errore massimo di su un picco di (meno dell').
Le due regole: risoluzione e estensione
- Passo in frequenza : dipende solo dalla durata totale della finestra di osservazione. Una finestra lunga dà una griglia fitta, "alta definizione". È la dualità di prima: campionare in frequenza con passo equivale a ripetere il segnale nel tempo con periodo , e questo non deve sovrapporre le copie (serve durata del segnale ).
- Estensione dell'asse : dipende solo dal passo di campionamento . È la metà della frequenza di campionamento : oltre non si può vedere, e quello che oltre c'è si ripiega dentro (aliasing).
- Numero di righe (l'ampiezza totale dell'asse, , divisa per il passo): con fisso, aumentare migliora la risoluzione ma peggiora l'estensione (e viceversa). Per migliorare entrambe bisogna aumentare .
Le variazioni: tre scelte di e
# VARIAZIONI - la stessa analisi con tre scelte diverse di N e T1
def spettro_rect(N, T1, A=2, T2=5):
dt = 2 * T1 / N
t = np.arange(N) * dt - T1
s = A * (np.abs(t) <= T2)
s = np.concatenate((s[N // 2:], s[:N // 2]))
df = 1 / (N * dt)
f = np.arange(-N // 2, N // 2) * df
S = dt * np.fft.fft(s)
S = np.concatenate((S[N // 2:], S[:N // 2]))
return t, f, S, dt, df
def S_vera(f, A=2, T2=5):
return A * 2 * T2 * np.sinc(f * 2 * T2)
casi = [(120, 70), (1000, 70), (1000, 13)]
risultati = {}
print(" N T1 dt df f_max=1/(2dt) righe per lobo S(0) errore (|f| <= 0.4)")
for N_, T1_ in casi:
t_, f_, S_, dt_, df_ = spettro_rect(N_, T1_)
risultati[(N_, T1_)] = (t_, f_, S_, dt_, df_)
sel = np.abs(f_) <= 0.4
err = np.max(np.abs(S_[sel] - S_vera(f_[sel])))
righe_lobo = 0.2 / df_ # il lobo principale e' largo 2 * (1/(2 T2)) = 0.2 Hz
print(f"{N_:>5} {T1_:>3} {dt_:>9.4f} {df_:>9.5f} {1 / (2 * dt_):>13.3f} {righe_lobo:>14.1f} {S_[N_ // 2].real:>12.4f} {err:>14.4f}")Risultato:
N T1 dt df f_max=1/(2dt) righe per lobo S(0) errore (|f| <= 0.4)
120 70 1.1667 0.00714 0.429 28.0 21.0000 1.3791
1000 70 0.1400 0.00714 3.571 28.0 19.8800 0.1205
1000 13 0.0260 0.03846 19.231 5.2 20.0200 0.0200| caso | asse | righe nel lobo principale ( Hz) | commento | |||
|---|---|---|---|---|---|---|
| , | s | Hz | Hz | griglia fitta, asse corto: aliasing forte | ||
| , | s | Hz | Hz | stessa risoluzione, asse 8 volte più lungo | ||
| , | s | Hz | Hz | asse molto esteso, griglia sparsa |
Caso 1: , ("poco fitto il segnale nel tempo: range di frequenze limitato; lunga estensione nel tempo: trasformata ad alta definizione"). Il passo di campionamento è grosso, s, e l'asse arriva solo a Hz: il lobo principale ( Hz) è disegnato con righe, ma si vedono pochi lobi laterali (solo quelli fino a Hz). Il rect è rappresentato da soli campioni, di larghezza s, e invece di . L'errore massimo sul confronto con la sinc per Hz è , cioè il del picco: qui l'aliasing è forte.
Caso 2: , . Stessa durata ( s) quindi stessa risoluzione Hz, ma s e l'asse è otto volte più lungo, Hz: ora il grafico mostra una trentina di lobi per lato (il file MATLAB limita l'asse a , dove cadono zeri ogni Hz). L'errore massimo scende a ( del picco).
Caso 3: , ("molto fitto il segnale nel tempo: range di frequenze ampio; corta estensione nel tempo: trasformata a bassa risoluzione"). La finestra è corta, s, quindi il passo in frequenza è grosso, Hz: nel lobo principale ( Hz) cadono solo righe e la curva sembra poligonale. L'asse è molto esteso, Hz, e l'errore sulle righe è piccolo, (un rect largo s sta bene nei s della finestra: , nessuna sovrapposizione nel tempo). Con s il rect verrebbe troncato dalla finestra, e con appena sopra s le copie periodiche del rect (periodo ) quasi si toccherebbero.
Un errore da non fare è leggere in questi tre casi la risoluzione come un effetto di da solo: il caso 1 e il 2 hanno diverso e la stessa risoluzione; il caso 2 e il 3 hanno lo stesso e risoluzioni diverse. Conta per e per l'estensione.
Quando compare l'aliasing e il legame con
I campioni del rect sono i campioni di un segnale non a banda limitata (la sinc di decade come e non si annulla mai). Campionarlo con passo equivale a replicare lo spettro con periodo (formula del campionamento, Campionamento e ricostruzioneIl campionamento $s_c(nT)=s(nT)$ trasforma un segnale continuo in uno discreto e, in frequenza, ripete lo spettro con periodo $F_c=1/T$: $S_c(f)=\sum_kS(f-kF_c)$. Se le repliche si sovrappongono si ha aliasing e il segnale non è recuperabile. Un interpolatore $\mathbb Z(T)\to\mathbb R$ con risposta impulsiva $g$ produce $\tilde s(t)=\sum_nT g(t-nT)s(nT)$ e $\tilde S=G,S_c$. Teorema del campionamento: se $s$ ha banda $B$ e $F_c\ge2B$, l'interpolatore ideale $G=\operatorname{rect}(f/F_c)$ ricostruisce esattamente $s(t)=\sum s(nT)\operatorname{sinc}(F_c(t-nT))$. Se le ipotesi non valgono c'è un errore, in banda e fuori banda, riducibile con un prefiltro anti-aliasing.Campionamento e ricostruzione →):
La FFT (cioè ) calcola proprio nei punti , non . Il confronto con la formula teorica ha quindi due cause di scarto: l'aliasing (le copie centrate in danno un contributo a ogni ) e la larghezza numerica del rect ( campioni, ecc.), che nella formula sono già incluse perché è il segnale campionato davvero. Per verificarlo, il blocco seguente confronta con una somma di copie della sinc vera:
# Il legame con il campionamento: S numerico = ripetizione (rep) dello spettro vero con periodo Fc = 1/dt
K = np.arange(-20000, 20001)
print(" N T1 errore massimo |S - rep S| (su tutte le righe con |f| <= 3) contro |S - S_vera|")
for N_, T1_ in casi:
t_, f_, S_, dt_, df_ = risultati[(N_, T1_)]
sel = np.where(np.abs(f_) <= 3)[0][::max(1, N_ // 120)] # un sottoinsieme di righe, per non rallentare
rep = np.array([np.sum(S_vera(f_[i] - K / dt_)) for i in sel])
print(f"{N_:>5} {T1_:>3} {np.max(np.abs(S_[sel] - rep)):.5f} {np.max(np.abs(S_[sel] - S_vera(f_[sel]))):.4f}")
# In f = 0 la ripetizione somma al valore vero 20 le code dei sinc centrati in k/dt
for N_, T1_ in casi:
t_, f_, S_, dt_, df_ = risultati[(N_, T1_)]
code = np.sum(S_vera(0 - K / dt_)) - S_vera(0)
print(f"N = {N_:>4}, T1 = {T1_:>2}: S(0) numerico = {S_[N_ // 2].real:.4f}, 20 + code dei sinc ripetuti = {20 + code:.4f} (Fc = 1/dt = {1 / dt_:.3f} Hz)") N T1 errore massimo |S - rep S| (su tutte le righe con |f| <= 3) contro |S - S_vera|
120 70 0.00004 1.4318
1000 70 0.00001 0.1549
1000 13 0.00000 0.0202
N = 120, T1 = 70: S(0) numerico = 21.0000, 20 + code dei sinc ripetuti = 21.0000 (Fc = 1/dt = 0.857 Hz)
N = 1000, T1 = 70: S(0) numerico = 19.8800, 20 + code dei sinc ripetuti = 19.8800 (Fc = 1/dt = 7.143 Hz)
N = 1000, T1 = 13: S(0) numerico = 20.0200, 20 + code dei sinc ripetuti = 20.0200 (Fc = 1/dt = 38.462 Hz)Lo scarto da è al più nei tre casi (contro dallo spettro vero ), e in la somma delle code porta il vero a (caso 1), (caso 2), (caso 3), esattamente i valori della FFT. Il numero non è un errore di calcolo: è il valore giusto della trasformata del segnale campionato.
L'entità dell'aliasing dipende da quanto vale lo spettro vero in : dal limite si ha circa in (caso 1, 7% di ), in (caso 2, meno dell'), in (caso 3, circa ). Più è piccolo, più il bordo dell'asse è lontano e più la coda ripiegata è bassa. In concreto, nel caso 1 le copie centrate in Hz si sovrappongono alla sinc vera proprio nella zona che si disegna:
Grafico interattivo: Caso N = 120, T1 = 70: il campionamento con dt = 7/6 s replica lo spettro S(f) = 20 sinc(10 f) con periodo Fc = 1/dt = 6/7 ≈ 0,857 Hz; le tre copie (originale e due vicine) si sovrappongono, e nella banda mostrata dalla FFT (|f| < 0,43 Hz, tratteggio) i lobi delle copie si sommano a quello vero
I tre confronti con il grafico analitico si possono rivedere con un solo disegno (il codice qui sotto riproduce la figura del file parte14_variazioni.m, con la curva teorica tratteggiata):
# I tre casi, come nel file parte14_variazioni.m
fig, assi = plt.subplots(3, 2, figsize=(11, 10))
fa = np.linspace(-3, 3, 6001)
for riga, (N_, T1_) in enumerate(casi):
t_, f_, S_, dt_, df_ = risultati[(N_, T1_)]
assi[riga, 0].plot(t_, A * (np.abs(t_) <= T2))
assi[riga, 0].set_xlabel('Tempo [s]'); assi[riga, 0].set_ylabel('Ampiezza [V]'); assi[riga, 0].set_ylim(-0.5, A + 0.5); assi[riga, 0].grid(True)
assi[riga, 0].set_title(f'N = {N_}, T1 = {T1_}')
assi[riga, 1].plot(fa, S_vera(fa), 'k--', label='analitica')
assi[riga, 1].plot(f_, S_.real, 'b.-', label='fft (parte reale)')
assi[riga, 1].set_xlabel('Frequenza [Hz]'); assi[riga, 1].set_ylabel('[Vs]'); assi[riga, 1].set_xlim(-3, 3); assi[riga, 1].grid(True); assi[riga, 1].legend()
plt.tight_layout()
plt.show()Controllo
- : (casi 1-2) e (caso 3); estensione : , , Hz.
- : ; ; (area numerica = numero di campioni a 2); valore vero .
- coincide con a meno di .
Versione ripasso
- Calcolo. sui campioni riordinati (tempo 0 davanti); confronto con .
- Risoluzione. : dipende dalla durata della finestra (lunga fitta). Estensione : dipende dal passo.
- Tre casi. , : , asse Hz, aliasing forte; , : stessa , asse Hz; , : , asse Hz, pochi punti per lobo.
- Aliasing. La fft dà (a ), non : sinc a banda illimitata, invece di .
- Condizione. (nessuna sovrapposizione nel tempo).