Skip to content

[FEAT] analysis.py: Implementar convolve_time() y convolve_frequency() #7

Description

@jero-scafati

Descripción

Implementar el filtrado de señales por dos caminos distintos: convolución directa en el dominio temporal, y convolución circular mediante multiplicación en el dominio de la frecuencia. Ambos métodos deben producir resultados equivalentes.

Contexto del TP

La consigna pide filtrar señales "mediante convolución en el dominio del tiempo y mediante convolución circular en frecuencia (usar propiedades)". Comparar ambos resultados permite verificar el Teorema de la Convolución.

Definición matemática

Convolución temporal:
y[n] = Σ_{k=-∞}^{∞} x[k] · h[n-k]
 
Teorema de la convolución (convolución circular en frecuencia):
y[n] = IFFT( FFT(x[n]) · FFT(h[n]) )
 
Para que la convolución circular sea equivalente a la lineal,
ambas señales deben extenderse con ceros hasta longitud L ≥ len(x) + len(h) - 1
(zero-padding).

Funciones a implementar

Archivo: core/dsp/analysis.py

convolve_time(signal, h)
convolve_frequency(signal, h)

Parámetros (ambas funciones)

Parámetro Tipo Descripción
signal np.ndarray Señal de entrada x[n]
h np.ndarray Respuesta al impulso del filtro (coeficientes)

Retorno (ambas funciones)

Variable Tipo Descripción
y np.ndarray Señal filtrada. Longitud: len(signal) + len(h) - 1 (convolución lineal completa)

Criterios de aceptación

Test Qué verifica
test_convolve_time_output_length len(y) == len(signal) + len(h) - 1
test_convolve_freq_output_length Igual que el anterior
test_convolve_equivalence Ambas funciones producen resultados casi idénticos (np.allclose con atol=1e-8)
test_convolve_time_delta Convolucionar con δ[n] reproduce la señal original
test_convolve_freq_delta Igual que el anterior
test_convolve_freq_zero_padding Con signal de largo 100 y h de largo 10, el resultado tiene largo 109 (no 100 ni 110)

Notas de implementación

  • convolve_time: usar np.convolve(signal, h, mode='full') — modo full da la convolución lineal completa
  • convolve_frequencyel zero-padding es un requisito de correctitud, no una optimización:
    L = len(signal) + len(h) - 1
    X = np.fft.fft(signal, n=L)   # el parámetro n hace el zero-padding automáticamente
    H_fft = np.fft.fft(h, n=L)
    Y = X * H_fft
    y = np.real(np.fft.ifft(Y))
    Sin zero-padding, la convolución circular produce aliasing temporal y el test de equivalencia con convolve_time nunca pasa.
  • El np.real() al final es importante: la parte imaginaria debe ser despreciable (ruido numérico), pero ifft devuelve complejo por defecto.

Archivos involucrados

  • core/dsp/analysis.py
  • core/dsp/tests/test_analysis.py

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions