Para interpretar mejor la operación se presenta una animación gráfica de h(t-τ) y y(t), para diferentes valores de t en el intervalo de observación [t_a,t_b] se incorpora la función graf_animada_xh_y().

Otros ejemplos de gif animado de gráficas con matplotlib, se pueden revisar en: Una partícula en movimiento circular del curso CCPG1001 Fundamentos de Programación.
# GRAFICA CON ANIMACION ------------
def graf_animada_xh_y(xt,ht,yt,t_a,t_b,
muestras=101,y_nombre='y',
reprod_x = 4,retardo = 200,
archivo_nombre = ''):
'''grafica animada convolucionx(t) y h(t)
en dos subgráficas con Parametros de animación trama/foto
y_nombre = 'ZSR' # o y nombre de resultado convolución
reprod_x = 4 # velocidad de reproducción
retardo = 200 # milisegundos entre tramas
archivo_nombre = '' # crea gif animado si hay nombre
'''
# grafica evaluación numerica
x_t = sym.lambdify(t,xt,modules=equivalentes)
h_t = sym.lambdify(t,ht,modules=equivalentes)
y_t = sym.lambdify(t,yt,modules=equivalentes)
ti = np.linspace(t_a,t_b,muestras)
xi = x_t(ti)
hi = h_t(ti)
yi = y_t(ti)
import matplotlib.animation as animation
# h(t-tau) para cada t
ht_tau = []
for tau in range(0,muestras,reprod_x):
ht_tau.append(h_t(ti[tau]-ti))
tramas = len(ht_tau) # tramas creadas
# figura con dos sub-graficas
fig_anim = plt.figure()
graf_a1 = fig_anim.add_subplot(211)
graf_a2 = fig_anim.add_subplot(212)
# grafico superior
x_linea, = graf_a1.plot(ti,xi, color='blue',
label=r'$x(\tau)$')
h_linea, = graf_a1.plot(ti,hi,color='magenta',
linestyle='dashed',
label=r'$h(\tau)$')
htau_linea, = graf_a1.plot(ti,ht_tau[0],
color='magenta',
label=r'$h(t-\tau)$')
punto1, = graf_a1.plot(0,0, color='magenta',marker=6)
# grafico inferior
color_y = 'green'
if y_nombre=='ZSR':
color_y ='dodgerblue'
y_linea, = graf_a2.plot(ti,yi, color=color_y,
label=y_nombre+'(t)')
punto2, = graf_a2.plot(0,0, color=color_y,marker=6)
y_sombra, = graf_a2.plot(ti,yi, color=color_y)
y_sombra.set_visible(False) # Para fijar leyend()
# Configura gráfica
titulo = r''+y_nombre+'(t)= x(t)$\circledast$h(t)'
graf_a1.set_title(titulo)
ymax1 = np.max([np.max(xi),np.max(hi)])*1.11
ymin1 = np.min([np.min(xi),np.min(hi)])-0.1*ymax1
graf_a1.set_xlim([t_a,t_b])
graf_a1.set_ylim([ymin1,ymax1])
graf_a1.set_xlabel(r'$\tau$')
graf_a1.legend()
graf_a1.grid()
ymax2 = np.max(yi)*1.1
ymin2 = np.min(yi)-0.1*ymax2
graf_a2.set_xlim([t_a,t_b])
graf_a2.set_ylim([ymin2,ymax2])
graf_a2.set_xlabel('t')
graf_a2.legend()
graf_a2.grid()
# cuadros de texto en gráfico
txt_x = (t_b+t_a)/2
txt_y = ymax1*(1-0.09)
txt_tau = graf_a1.text(txt_x,txt_y,'t='+str(t_a),
horizontalalignment='center')
def trama_actualizar(i,ti,ht_tau):
# actualiza cada linea
htau_linea.set_xdata(ti)
htau_linea.set_ydata(ht_tau[i])
hasta = i*reprod_x
porusar = (muestras-reprod_x*(i+1))
if porusar>=reprod_x: # en intervalo
y_linea.set_xdata(ti[0:hasta])
y_linea.set_ydata(yi[0:hasta])
punto1.set_xdata([ti[hasta]])
punto1.set_ydata([0])
punto2.set_xdata([ti[hasta]])
punto2.set_ydata([0])
else: # insuficientes en intervalo
y_linea.set_xdata(ti)
y_linea.set_ydata(yi)
punto1.set_xdata([ti[-1]])
punto1.set_ydata([0])
punto2.set_xdata([ti[-1]])
punto2.set_ydata([0])
# actualiza texto
t_trama = np.around(ti[i*reprod_x],4)
txt_tau.set_text('t= '+str(t_trama))
return(htau_linea,y_linea,punto1,punto2,txt_tau)
def trama_limpiar(): # Limpia Trama anterior
htau_linea.set_ydata(np.ma.array(ti, mask=True))
y_linea.set_ydata(np.ma.array(ti, mask=True))
punto1.set_ydata(np.ma.array(ti, mask=True))
punto2.set_ydata(np.ma.array(ti, mask=True))
txt_tau.set_text('')
return(htau_linea,y_linea,punto1,punto2,txt_tau)
i = np.arange(0,tramas,1) # Trama contador
ani = animation.FuncAnimation(fig_anim,trama_actualizar,i ,
fargs = (ti,ht_tau),
init_func = trama_limpiar,
interval = retardo,
blit=True)
# Guarda archivo GIF animado o video
if len(archivo_nombre)>0:
ani.save(archivo_nombre+'_animado.gif',
writer='imagemagick')
#ani.save(archivo_nombre+'_video.mp4')
plt.draw()
#plt.show()
return(ani)
# grafica animada de convolución
n_archivo = '' # sin crear archivo gif animado
n_archivo = 'convolucion01' # requiere 'imagemagick'
figura_animada = graf_animada_xh_y(x,h,y,t_a,t_b,
muestras, reprod_x = 4,
archivo_nombre = n_archivo)
plt.show()
Para obtener un gif animado se debe asignar un 'archivo_nombre' para identificar el ejercicio; si se mantiene el nombre vacio '', solamente se crea la gráfica. El resultado se almacena en el archivo_nombre_animado.gif del directorio de trabajo,
La función también se incorpora a telg1001.py para su uso posterior en los ejercicios