Estoy tratando de visualizar directamente la relación entre los coeficientes de detalle de la transformada wavelet discreta (DWT) y la señal original / su reconstrucción. El objetivo es mostrar su relación de forma intuitiva. Me gustaría preguntar (ver preguntas a continuación): si la idea y el proceso que se me ocurren son correctos hasta ahora, y si estoy en lo cierto, podría ser mejor restar la aproximación del primer nivel de la señal original antes de visualizar su relación .
Ejemplo mínimo
Este es el ejemplo mínimo en el que baso mi explicación, utilizando los datos de ejemplo de ECG de Pythonpywavelets
, que tiene 1024 valores, como una simple señal 1D:
import pywt
import pywt.data
import numpy as np
import matplotlib.pyplot as plt
x = pywt.data.ecg()
plt.plot(x)
plt.legend(['Original signal'])
La descomposición se realiza utilizando un Symmlet 5 con un total de 6 niveles:
w = pywt.Wavelet('sym5')
plt.plot(w.dec_lo)
coeffs = pywt.wavedec(x, w, level=6)
La reconstrucción (con pérdida) de la señal funciona como se espera cuando se omiten intencionalmente los coeficientes de detalle de los niveles superiores (las señales se trazan en una escala x uniforme [0,1] por conveniencia):
def reconstruction_plot(yyy, **kwargs):
"""Plot signal vector on x [0,1] independently of amount of values it contains."""
plt.plot(np.linspace(0, 1, len(yyy)), yyy, **kwargs)
reconstruction_plot(pywt.waverec(coeffs, w)) # full reconstruction
#reconstruction_plot(pywt.waverec(coeffs[:-1] + [None] * 1, w)) # leaving out detail coefficients up to lvl 5
#reconstruction_plot(pywt.waverec(coeffs[:-2] + [None] * 2, w)) # leaving out detail coefficients up to lvl 4
#reconstruction_plot(pywt.waverec(coeffs[:-3] + [None] * 3, w)) # leaving out detail coefficients up to lvl 3
reconstruction_plot(pywt.waverec(coeffs[:-4] + [None] * 4, w)) # leaving out detail coefficients up to lvl 2
#reconstruction_plot(pywt.waverec(coeffs[:-5] + [None] * 5, w)) # leaving out detail coefficients up to lvl 1
reconstruction_plot(pywt.waverec(coeffs[:-6] + [None] * 6, w)) # leaving out all detail coefficients = reconstruction using lvl1 approximation only
plt.legend(['Full reconstruction', 'Reconstruction using detail coefficients lvl 1+2', 'Reconstruction using lvl 1 approximation only'])
El DWT anterior produce un vector de aproximación de nivel 1 de 24 valores, un vector de coeficiente de detalles de nivel 1 de 24 valores, un vector de detalle de nivel 2 de 40 valores, el nivel 3 de 72 valores, el nivel 4 de 135 valores, el nivel 5 de 262 valores y el nivel 6 de 516 valores:
plt.stem(coeffs[1]); plt.legend(['Lvl 1 detail coefficients'])
plt.stem(coeffs[2]); plt.legend(['Lvl 2 detail coefficients'])
plt.stem(coeffs[3]); plt.legend(['Lvl 3 detail coefficients'])
plt.stem(coeffs[4]); plt.legend(['Lvl 4 detail coefficients'])
plt.stem(coeffs[5]); plt.legend(['Lvl 5 detail coefficients'])
plt.stem(coeffs[6]); plt.legend(['Lvl 6 detail coefficients'])
Parece que vemos patrones claros alrededor de los picos en las señales originales (también preste atención a la escala y de los gráficos de arriba).
Ahora a mis preguntas:
- ¿Es correcto que podamos relacionar directamente esos coeficientes con la señal? La amplitud del coeficiente corresponde a la amplitud con la que se produce la wavelet en la señal (eje y), y la posición del coeficiente corresponde al tiempo (eje x). ¿O hay algo en el medio que debemos considerar?
Después del DWT, la aproximación final lvl1 permanece. ¿Tiene sentido no visualizar la relación de los coeficientes de detalle con la señal original, sino con la señal original menos la aproximación lvl1? (Sé que lo más probable es que también vea la relación entre los coeficientes y la señal sin hacer esto, ver, por ejemplo, las gráficas a continuación. Es solo para esto tiene sentido o no. Si tiene sentido para los coeficientes de detalle lvl1, entonces también podría tener sentido para Coeficientes de detalle lvl2 para comparar con la señal original menos la aproximación lvl2, ¿verdad?). Un ejemplo:
# Reconstruction of signal using just lvl1 approximation approx_lvl1 = pywt.waverec(coeffs[:-6] + [None] * 6, w) # interpolate to original amount of samples (necessary due to numeric solution of transformation not yielding same amount of values) approx_lvl1_interp = np.interp(x=np.arange(0, 1024), xp=np.linspace(0, 1024, len(approx_lvl1)), fp=approx_lvl1) x_without_lvl1approx = x - approx_lvl1_interp
La visualización directa de la relación entre los coeficientes de detalle y la señal que uso simplemente traza tanto la señal como los coeficientes en un eje x de [0,1]. Conceptualmente, esto debería ser válido, pero no estoy seguro de si realmente necesitaría un desplazamiento hacia los márgenes (por ejemplo, el primer y el último coeficiente del vector que no se coloca al principio o al final de la señal):
def reconstruction_stem(yyy, **kwargs): """Plot coefficient vector on x [0,1] independently of amount of values it contains.""" plt.stem(np.linspace(0, 1, len(yyy)), yyy, **kwargs) reconstruction_plot(x, color='orange') reconstruction_plot(x_without_lvl1approx, color='red') reconstruction_stem(coeffs[1]) plt.legend(['Original signal', 'Original signal - lvl1 approximation', 'Detail coefficients'])
¿Existe una explicación intuitiva para los coeficientes fuertes que no están directamente en las posiciones de los picos en los datos originales (por ejemplo, en el nivel 1, el más bajo (negativo más fuerte) en alrededor de 0.25, así como el más alto (positivo más fuerte) en torno a 0.75 )? Aunque hay un patrón claro (retraso positivo + amplitud negativa, retraso negativo + amplitud positiva), me parecen un poco "lejanos". Pero probablemente haya una buena explicación para eso.
¡Gracias por responder!