7.1.6 LTI DT – H[z] Diagrama de bloques con «1/z» – ejercicios

Referencia: Lathi 5.4 p519. Oppenheim 10.8 p783, Hsu Ejercicio 4.34 p201

Dada la similitud entre sistemas LTIC y LTID, las convenciones para diagramas de bloques  y las reglas de interconexión son idénticas a los sistemas contínuos. Los diagramas mostrados se realizan con el programa Xcos de SciLab.

Una función de transferencia general se expresa como:

H(z) = \frac{b_0 z^N +b_1 z^{N-1} + \text{ ... } + b_{N-1} z + b_N}{z^N + a_1 z^{N-1} +\text{ ... } + a_{N-1}z +a_N}

Ejemplo 1. H(z)

Referencia : Lathi 5.8a p522

H(z) =\frac{2}{z+5}

La función de transferencia es de primer orden (N=1), por lo que solo se usará un retraso para el diagrama. Los coeficientes de retroalimentación de retraso y adelanto son:

a1= 5 y b0 = 0, b1=2

La imagen presenta dos formas de realizar los diagramas

Ejemplo 2. H(z)

Referencia : Lathi 5.8b p522

H(z) =\frac{4z+28}{z+1}

la función de transferencia también es de primer orden (N=1), los coeficientes de retraso y adelanto son:

a1= 1 y b0 = 4, b1=28

La imagen presenta dos formas de realizar el diagrama de bloques

Ejemplo 3. H(z)

Referencia : Lathi 5.8c p522

H(z) =\frac{z}{z+7}

la función de transferencia también es de primer orden (N=1), los coeficientes de retraso y adelanto son:

a1= 7 y b0 = 1, b1=0

Ejemplo 4. H(z)

Referencia : Lathi 5.8d p522

H(z) =\frac{4z+28}{z^2+6z+5}

la función de transferencia también es de segundo orden (N=2), los coeficientes de retraso y adelanto son:

a1= 6, a2= 5 y b0 = 0, b1=4, b2=28

Ejemplo 5. Sistema LTI D

Referencia: Ejemplo Openheim 10.28 p784

Considere el sistema LTI causal descrito mediante:

y[n] - \frac{1}{4} y[n-1] = x[n]

con función del sistema:

H(z) =\frac{1}{1- \frac{1}{4} z^{-1} }

Aqui z-1 es la función del sistema con retraso unitario. El diagrama de bloques en la figura contiene un lazo de retroalimentación.

y[n] -\frac{1}{4} z^{-1} y[n] = x[n] y[n] = x[n] + \frac{1}{4} z^{-1} y[n]


Ejemplo 6. Función H(z)

Referencia: Ejemplo Openheim 10.29 p785

Considere un sistema LTI causal con función del sistema:

H(z) = \frac{ 1 - 2 z^{-1} }{ 1 - \frac{1}{4} z^{-1} }

La función se puede separar en bloque de denominador y numerador, semejante a los polinomios Q(E)  y P(E).

= \Bigg[\frac{1}{1 - \frac{1}{4}z^{-1}} \Bigg] \Bigg[ 1 - 2z^{-1} \Bigg]

Se observa en el diagrama (a) que z-1 se encuentra duplicado pues ambos bloques toman la misma señal para aplicarle un atraso, cada uno le da a una ganancia diferente. Por lo que un solo bloque z-1 puede realizar la misma operación.

En el mundo de los circuito digitales y componentes, la situación se interpreta como un componente duplicado, lo que tiene implicaciones de costos de implementación, recuerde el tema cuando construye un circuito digital usando puertas lógicas y registros.

7.1.5 Transformada z Inversa con Sympy-Python

La Transformada z  inversa, usa la Tabla de Pares f[n] y F[z] y los algoritmos para buscar una expresión semejante F.match() en conjunto con la tabla de propiedades y los algoritmos desarrollados en la sección anterior. El resultado se integra desde telg1001.py y se muestra en los siguientes ejemplos:

Ejemplo 1.  Transformada z inversa de una fracción X[1/z]

Referencia: Oppenheim Ejemplo 10.13 p761, Lathi Ejemplo 5.1 p490

Continuando con el ejercicio presentado para convertir x[n] a X[z], se tiene que:

X[z] = \frac{1}{1-a z^{-1}}\text{ , } |z|>|a| X[z] = \frac{z}{z-a}\text{ , } \Big|z|>|a|

siendo la expresión de ingreso al algoritmo:

F = z/(z - 2)

el resultado es:

f[n] : (2**n*Heaviside(n), Abs(z) > 2, True)
>>> 

Ejemplo 1a. Instrucciones Python

# transformada z propiedades con Sympy
# aplicar luego de buscar en tabla de pares
import sympy as sym
import telg1001 as fcnm

# INGRESO
n = sym.Symbol('n', real=True)
z = sym.Symbol('z')
u = sym.Heaviside(n)

# (a**n)*f[n] <--> F(z/a)
F = z/(z - 2)  #f = (2**n)*u

# PROCEDIMIENTO
fn = fcnm.inverse_z_transform(F,z,n)

# SALIDA
print('f[n] :',fn)

El algoritmo presentado puede ser tomado como punto de partida para los siguientes ejercicios. Realizado para explicación conceptual.

Ejemplo 2. Transformada z inversa usando expansión en fracciones parciales

Referencia: Lathi 5.3 a

Encuentre la transformada z inversa para:

F[z] = \frac{8z-19}{(z-2)(z-3)}

el ingreso para el algoritmo del ejercicio anterior es:

F = (8*z-19)/((z-2)*(z-3))

con el resultado siguiente:

f[n] : (9*2**n + 10*3**n)*Heaviside(n)/6 - 19*DiracDelta(n)/6

activando la variable sym.SYMPY_DEBUG=True, se observa el proceso de fracción parcial modificada, la búsqueda en la tabla, y aplicación de una propiedad de la transformada z.

inverse_z_transform(F,z,n): (8*z - 19)/((z - 3)*(z - 2))

apart_z(F) : (8*z - 19)/((z - 3)*(z - 2))
_simplify_z: (8*z - 19)/((z - 3)*(z - 2))
  P_leadcoef: 8  ; P_zc: 1  ; P: z - 19/8
  _simplify_z k_sign: 1  ; k: 8  ; P_zc: 1  ; Q_zc: 1
    F[z]: (z - 19/8)/((z - 3)*(z - 2))
_simplify_z: (z - 19/8)/(z*(z - 3)*(z - 2))
  P_leadcoef: 8  ; P_zc: 1  ; P: z - 19/8
  Q_leadcoef: 8  ; Q_zc: z  ; Q: (z - 3)*(z - 2)
  _simplify_z k_sign: 1  ; k: 1  ; P_zc: 1  ; Q_zc: z
    F[z]: (z - 19/8)/((z - 3)*(z - 2))
  P: (8*z - 19)/8 
  Q: (z - 3)*(z - 2) 
  P_degree: 1  ; P_zeros: {19/8: 1} 
  Q_degree: 3  ; Q_poles: {3: 1, 2: 1, 0: 1}
  apart(F/z): 3/(16*(z - 2)) + 5/(24*(z - 3)) - 19/(48*z)
  ma_Qk: {a_: 48, b_: 0, c_: 1}  ; ma_Qk2: {b_: 48, a_: 0, c_: 0}
_simplify_z: -19/(48*z)
  P_leadcoef: -19  ; P_zc: 1  ; P: 1
  Q_leadcoef: 48  ; Q_zc: z  ; Q: 1
  _simplify_z k_sign: -1  ; k: 19/48  ; P_zc: 1  ; Q_zc: z
    F[z]: 1
  ma_Qk: {a_: 16, b_: -32, c_: 1}  ; ma_Qk2: {b_: 16, c_: -32, a_: 0}
_simplify_z: 3/(16*(z - 2))
  P_leadcoef: 3  ; P_zc: 1  ; P: 1
  Q_leadcoef: 16  ; Q_zc: 1  ; Q: z - 2
  _simplify_z k_sign: 1  ; k: 3/16  ; P_zc: 1  ; Q_zc: 1
    F[z]: 1/(z - 2)
  ma_Qk: {a_: 24, b_: -72, c_: 1}  ; ma_Qk2: {b_: 24, c_: -72, a_: 0}
_simplify_z: 5/(24*(z - 3))
  P_leadcoef: 5  ; P_zc: 1  ; P: 1
  Q_leadcoef: 24  ; Q_zc: 1  ; Q: z - 3
  _simplify_z k_sign: 1  ; k: 5/24  ; P_zc: 1  ; Q_zc: 1
    F[z]: 1/(z - 3)

 apart z*(Fz/z)  : 3*z/(2*(z - 2)) + 5*z/(3*(z - 3)) - 19/6 

 apart_z(F) as partial fractions: (-19/6, 3*z/(2*(z - 2)), 5*z/(3*(z - 3)))
  term_k[z]: -19/6
[0] _z_pairs_prop_inverse ----
_simplify_z: -19/6
  P_leadcoef: -19  ; P_zc: 1  ; P: 1
  Q_leadcoef: 6  ; Q_zc: 1  ; Q: 1
  _simplify_z k_sign: -1  ; k: 19/6  ; P_zc: 1  ; Q_zc: 1
    F[z]: 1
 _z_pairs_table match: 
  F: 1
  z_pair F[z]: 1  ; ma_z: {}
  z_pair f[n]: DiracDelta(n)
  try,check  : True -> True
[0]   pair f[n]: (-19*DiracDelta(n)/6, True, True)
  term_k[n]: (-19*DiracDelta(n)/6, True, True)
  term_k[z]: 3*z/(2*(z - 2))
[0] _z_pairs_prop_inverse ----
_simplify_z: 3*z/(2*(z - 2))
  P_leadcoef: 3  ; P_zc: 1  ; P: z
  Q_leadcoef: 2  ; Q_zc: 1  ; Q: z - 2
  _simplify_z k_sign: 1  ; k: 3/2  ; P_zc: 1  ; Q_zc: 1
    F[z]: z/(z - 2)

[1] z_properties_inverse_z_transform
  P: z 
  Q: z - 2 
  P_degree: 1  ; P_zeros: {0: 1} 
  Q_degree: 1  ; Q_poles: {2: 1}
  ma_P1 (a*z+ b):    {a_: 1, b_: 0}
  ma_Q1 (a*z-b)**c : {a_: 1, b_: 2, c_: 1}

 _z_property multiply (a**n)*f[n] <--> F(z/a) 
 k_sign: 1 ; k: 3/2  ; k_b: 2
 F[z]: z/(z - 1)
[2] _z_pairs_prop_inverse ----
_simplify_z: z/(z - 1)
    F[z]: z/(z - 1)
 _z_pairs_table match: 
  F: z/(z - 1)
  z_pair F[z]: z/(z - 1)  ; ma_z: {}
  z_pair f[n]: Heaviside(n)
  try,check  : True -> True
[2]   pair f[n]: (Heaviside(n), Abs(z) > 1, True)

  _z_property multiply (a**n)*f[n]:
  (3*2**n*Heaviside(n)/2, Abs(z) > 2, True)
[1]  _z_properties_inverse f[n]: (3*2**n*Heaviside(n)/2, Abs(z) > 2, True)
[0]   prop f[n]: (3*2**n*Heaviside(n)/2, Abs(z) > 2, True)
  term_k[n]: (3*2**n*Heaviside(n)/2, Abs(z) > 2, True)
  term_k[z]: 5*z/(3*(z - 3))
[0] _z_pairs_prop_inverse ----
_simplify_z: 5*z/(3*(z - 3))
  P_leadcoef: 5  ; P_zc: 1  ; P: z
  Q_leadcoef: 3  ; Q_zc: 1  ; Q: z - 3
  _simplify_z k_sign: 1  ; k: 5/3  ; P_zc: 1  ; Q_zc: 1
    F[z]: z/(z - 3)

[1] z_properties_inverse_z_transform
  P: z 
  Q: z - 3 
  P_degree: 1  ; P_zeros: {0: 1} 
  Q_degree: 1  ; Q_poles: {3: 1}
  ma_P1 (a*z+ b):    {a_: 1, b_: 0}
  ma_Q1 (a*z-b)**c : {a_: 1, b_: 3, c_: 1}

 _z_property multiply (a**n)*f[n] <--> F(z/a) 
 k_sign: 1 ; k: 5/3  ; k_b: 3
 F[z]: z/(z - 1)
[2] _z_pairs_prop_inverse ----
_simplify_z: z/(z - 1)
    F[z]: z/(z - 1)
 _z_pairs_table match: 
  F: z/(z - 1)
  z_pair F[z]: z/(z - 1)  ; ma_z: {}
  z_pair f[n]: Heaviside(n)
  try,check  : True -> True
[2]   pair f[n]: (Heaviside(n), Abs(z) > 1, True)

  _z_property multiply (a**n)*f[n]:
  (5*3**n*Heaviside(n)/3, Abs(z) > 3, True)
[1]  _z_properties_inverse f[n]: (5*3**n*Heaviside(n)/3, Abs(z) > 3, True)
[0]   prop f[n]: (5*3**n*Heaviside(n)/3, Abs(z) > 3, True)
  term_k[n]: (5*3**n*Heaviside(n)/3, Abs(z) > 3, True)

 f[n]: 3*2**n*Heaviside(n)/2 + 5*3**n*Heaviside(n)/3 - 19*DiracDelta(n)/6
 f[n]: (9*2**n + 10*3**n)*Heaviside(n)/6 - 19*DiracDelta(n)/6
f[n] : (9*2**n + 10*3**n)*Heaviside(n)/6 - 19*DiracDelta(n)/6
>>> 

7.1.4 Transformada z Inversa – Conceptos

Referencia: Lathi 5.1-1 p495, Oppenheim 10.3 p757

Muchas de las transformadas X[z] de interés práctico son fracciones de polinomios en z, que pueden ser expresadas como una suma de fracciones parciales cuya inversa puede ser revisada en una tabla de transformadas z.

El método de fracciones parciales funciona dado que para cada x[n] transformable con n≥0 le corresponde una X[z] única definida para |z|>a y viceversa. Para lo mostrado, se supone que se usa la fracción parcial mas simple.

Ejemplo 1a.  Transformada z inversa de una fracción X[1/z]

Referencia: Oppenheim Ejemplo 10.13 p761, Lathi Ejemplo 5.1 p490

Continuando con el ejercicio presentado para convertir x[n] a X[z], se tiene que:

X[z] = \frac{1}{1-a z^{-1}}\text{ , } |z|>|a|

la expresión se puede expandir en series se potencias y obtener los primeros términos de la secuencia de x[n]. Los términos son útiles si se se requieren los m primeros términos de la secuencia, es decir n se encuentra en [0,m-1]

X[z]: 
  z   
------
-a + z

 F[z]:
         2    3    4    5    6                 
    a   a    a    a    a    a     /1          \
1 + - + -- + -- + -- + -- + -- + O|--; z -> oo|
    z    2    3    4    5    6    | 7         |
        z    z    z    z    z     \z          /
Términos x[n] entre[0,7]
[1, a, a**2, a**3, a**4, a**5, a**6]

 x[n] con a= 1/2
[1.0, 0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625] 

Al final de la serie F[z] se muestra un término con el orden del error.

De los términos mostrados, se observa que X[n] = an

Usando por ejemplo a=1/2, se obtiene como resultado de x[n],

Transformada Z Ej01 X[z] x[n]

>>> xi
[1.0, 0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625]

Ejemplo 1a. Instrucciones Python

# transformada z inversa de X[z]
import sympy as sym

# INGRESO
z = sym.symbols('z',)
n = sym.symbols('n', positive=True)
a = sym.symbols('a')
u = sym.Heaviside(n)

Xz = 1/(1-a*z**(-1))

# valor a como racional en dominio 'ZZ' enteros
a_k = sym.Rational(1/2).limit_denominator(100)

m = 7   # Términos a graficar

# PROCEDIMIENTO
# Series de potencia z**(-1)
Fz = sym.series(Xz,z**(-1), n=m)

# Terminos de X[n]
xn = []
termino = Fz.args
for i in range(0,m,1):
    xn.append(termino[i]*(z**i))
 
# SALIDA
print('X[z]: ')
sym.pprint(Xz)
print('\n F[z]:')
sym.pprint(Fz)
print('\n Términos x[n] entre [0,'+str(m)+']')
print(xn)

# GRAFICA valores ---------------
import numpy as np
import matplotlib.pyplot as plt
# Terminos de X[n]
xi = [] ; ki=[]
for i in range(0,m,1):
    valor = xn[i].subs({z:1,a:a_k})
    xi.append(float(valor))
    ki.append(i)

print('\n x[n] con a=',a_k)
print(xi)

# grafica entrada x[n]
plt.axvline(0,color='grey')
plt.stem(ki,xi,label='x[n]')
plt.xlabel('n')
plt.ylabel('x[n]')
plt.title(r'x[n]= $'+str(sym.latex(xn))+'$')
plt.grid()
plt.show()

Ejemplo 1b.  Transformada z inversa de una fracción dada con X[z]

Referencia: Oppenheim Ejemplo 10.13 p761, Lathi Ejemplo 5.1 p490

Si la expresión se usa de la forma simplificada, que es la más común para tratar las expresiones con Sympy, el algoritmo anterior para las series no realiza la misma respuesta.

X[z] = \frac{z}{z-a}\text{ , } \Big|z|>|a| X[z] = \frac{1}{1-a z^{-1}}\text{ , } \Big|z|>|a|

Para este caso se multiplica el numerador y denominador por 1/z, obteniendo la expresión del ejemplo anterior. Para generar la serie se realiza el, cambio de variable Z=1/z para generar la serie sobre Z. Luego se restablece en la expresión antes de mostrar los términos, y se obtiene el mismo resultado.

De los términos mostrados, se observa que X[n] = an

Ejemplo 1b. Instrucciones en Python

# transformada z inversa de X[z]
# supone que la expresión son fracciones parciales
import sympy as sym

# INGRESO
z = sym.symbols('z')
n = sym.symbols('n', integer=True, positive=True)
a = sym.symbols('a')

Xz = z/(z-a)

# valor a como racional en dominio 'ZZ' enteros
a_k = sym.Rational(1/2).limit_denominator(100)

m = 7   # Términos a graficar

# PROCEDIMIENTO
# expresión Xz con z para aplicar serie
# separa numerador y denominador
[Pz,Qz] = Xz.as_numer_denom()
Pz = (Pz*(1/z)).expand(1/z)
Qz = (Qz*(1/z)).expand(1/z)

# cambia Z por 1/z
Z = sym.symbols('Z')
PZ = Pz.subs(1/z,Z)
QZ = Qz.subs(1/z,Z)
XZ = PZ/QZ

# Series de potencia de Z
FZ = sym.series(XZ,Z, n=m)
Fz = FZ.subs(Z,1/z) # restituye 1/z

# Terminos de X[n]
xn = []
termino = Fz.args
for i in range(0,m,1):
    xn.append(termino[i]*(z**i))

# SALIDA
print('X[z]: ')
sym.pprint(Xz)
print('\n F[z]:')
sym.pprint(Fz)
print('Términos x[n] entre[0,'+str(m)+']')
print(xn)

# GRAFICA valores ---------------
import numpy as np
import matplotlib.pyplot as plt
# Terminos de X[n]
xi = [] ; ki=[]
for i in range(0,m,1):
    valor = xn[i].subs({z:1,a:a_k})
    xi.append(float(valor))
    ki.append(i)

print('\n x[n] con a=',a_k)
print(xi)

# grafica entrada x[n]
plt.axvline(0,color='grey')
plt.stem(ki,xi,label='x[n]')
plt.xlabel('n')
plt.ylabel('x[n]')
plt.title(r'x[n]= $'+str(sym.latex(xn))+'$')
plt.grid()

plt.show()

El algoritmo presentado puede ser tomado como punto de partida para los siguientes ejercicios. Realizado para explicación conceptual.

7.1 Transformada z – Sumatoria con Sympy-Python

Referencia: Lathi 5.1 p488, Oppenheim 10.1 p741

Se define como X[z] a la transformada z de una señal x[n] como

X[z] = \sum_{n=-\infty}^{\infty} x[n] z^{-n}

Por razones semejantes a las descritas en la unidad 4 para transformadas de Laplace, es conveniente considerar la transformada z unilateral. Dado que muchos de los sistemas y señales son causales, en la práctica se considera que las señales inician en n=0 (señal causal), la definición de la transformada z unilateral es la misma que la bilateral. excepto por los limites de la sumatoria que son [0,∞]

X[z] = \sum_{n=0}^{\infty} x[n] z^{-n}

Ejemplo 1. Transformada z de exponencial causal

Referencia: Lathi ejemplo 5.1 p490, Oppenheim ejemplo 10.1 p743

Encuentre la Transformada z y la correspondiente ROC para la señal x[n]

x[n] = a ^{n} \mu[n]

Transformada Z Ej01x[n]

1.1 Desarrollo analítico

por definición

X[z] = \sum_{n=0}^{\infty} a ^{n} \mu[n] z^{-n}

dado que μ[n]=1 para todo n≥0,

X[z] = \sum_{n=0}^{\infty} \Big( a^n \Big) \Big(\frac{1}{z} \Big)^{n} = \sum_{n=0}^{\infty} \Big(\frac{a}{z} \Big)^{n} =1 + \Big(\frac{a}{z} \Big)^{1}+\Big(\frac{a}{z} \Big)^{2}+\Big(\frac{a}{z} \Big)^{3}+\text{...}

revisando la progresión geométrica,

1+x+x^2+x^3+\text{...} = \frac{1}{1+x} \text{ , }|x|<1

y aplicando en la expresión del problema, se tiene:

X[z] = \frac{1}{1-\frac{a}{z}}\text{ , } \Big|\frac{a}{z}\Big| <1 X[z] = \frac{z}{z-a}\text{ , } |z|>|a|

observe que X[z] existe solo si |z|>|a|. Para |z|<|a| la sumatoria no converge y tiende al infinito. Por lo que, la Región de Convergencia ROC de X[z] es la región sombreada de un círculo de radio |a| centrado en el origen en el plano z.

Transformada Z Ej01 ROC
Luego se puede mostrar que la transformada z de la señal -an u[-(n+1)] también es z/(z-a). Sin embargo la región de convergencia en éste caso es |z|<|a|. Se observa que la transformada z inversa no es única, sin embargo,al restringir la transformada inversa a causal, entonces la transformada inversa es única como la mostrada.

Transformada Z Ej01 Xz

1.2 Transformada z con Sympy-Python

En Sympy de Python existe la función sym.summation(), que se usa para generar la expresión del resultado para la transformada z.

f[n]: 
 n
a 

 F[z] desde sumatoria:
    1     |a|     
(-------, |-| < 1)
   a      |z|     
 - - + 1          
   z              

 F[z] simplificada
  z   
------
-a + z

 ROC: 
|a|    
|-| < 1 
|z| 

{Q_polos:veces}: {a: 1} 
{P_ceros:veces}: {0: 1} 
>>> 

Instrucciones en Python

# transformada z de x[n]u[n]
import sympy as sym

# INGRESO
z = sym.symbols('z')
n = sym.symbols('n', positive=True)
a = sym.symbols('a')
u = sym.Heaviside(n)

fn = (a**n)*u

# valor a como racional en dominio 'ZZ' enteros
a_k = sym.Rational(1/2).limit_denominator(100)
m   = 7        # Términos a graficar
muestras = 101 # dominio z

# PROCEDIMIENTO
fnz = fn*(z**(-n)) # f(n,z) para sumatoria
# sumatoria transformada z
Fz_sum = sym.summation(fnz,(n,0,sym.oo))
Fz_eq  = Fz_sum.args[0]  # primera ecuacion e intervalo
Fz = Fz_eq[0].simplify() # solo expresion

ROC = Fz_eq[1]  # condicion ROC

# polos y ceros de Fz
[P,Q] = Fz.as_numer_denom()
P = sym.poly(P,z)
Q = sym.poly(Q,z)
P_ceros = sym.roots(P)
Q_polos = sym.roots(Q)

# SALIDA
print('f[n]: ')
sym.pprint(fn)
print('\n F[z] desde sumatoria:')
sym.pprint(Fz_eq)
print('\n F[z] simplificada')
sym.pprint(Fz)
print('\n ROC: ')
sym.pprint(ROC)
print('\n {Q_polos:veces}:',Q_polos)
print(' {P_ceros:veces}:',P_ceros)

La parte gráfica se desarrolla reutilizando algunas funciones de los algoritmos telg1001.py

Ser requiere dar valor a la constante ‘a‘ y se sustituye en las funciones con a_k=1/2. Para actualizar los polos, se usa la función buscapolos() realizada en la unidad 4.3.2, añadiendo en la función la sustitución en F[z] de variable independiente a F(s) para que sea transparente el cálculo. Lo mismo se aplica a la grafica de la transformada F[z] y los resultados son los mostrados.

# GRAFICA  -----------
import numpy as np
import matplotlib.pyplot as plt
import telg1001 as fcnm

def graficar_Fz_polos(Fz,Q_polos={},P_ceros={},
                z_a=1,z_b=0,muestras=101,f_nombre='F',
                solopolos=False):
    ''' polos y ceros plano z imaginario
    '''
    fig_zROC, graf_ROC = plt.subplots()
    # limite con radio 1
    radio1 = plt.Circle((0,0),1,color='lightsalmon',
                        fill=True)
    radio2 = plt.Circle((0,0),1,linestyle='dashed',
                        color='red',fill=False)
    graf_ROC.add_patch(radio1)
    for unpolo in Q_polos.keys():
        [r_real,r_imag] = unpolo.as_real_imag()
        unpolo_radio = np.abs(unpolo)
        unpolo_ROC = plt.Circle((0,0),unpolo_radio,
                          color='lightgreen',fill=True)
        graf_ROC.add_patch(unpolo_ROC)
    graf_ROC.add_patch(radio2) # borde r=1
    graf_ROC.axis('equal')
    # marcas de r=1 y polos
    for unpolo in Q_polos.keys():
        x_polo = sym.re(unpolo)
        y_polo = sym.im(unpolo)
        etiqueta = 'polo: '+str(unpolo)
        graf_ROC.scatter(x_polo,y_polo,marker='x',
                        color='red',label = etiqueta)
        etiqueta = "("+str(float(x_polo)) + ','
        etiqueta = etiqueta + str(float(y_polo))+")"
        plt.annotate(etiqueta,(x_polo,y_polo), rotation=45)
    # marcas de ceros
    for uncero in P_ceros.keys():
        x_cero = sym.re(uncero)
        y_cero = sym.im(uncero)
        etiqueta = 'cero: '+str(uncero)
        graf_ROC.scatter(x_cero,y_cero,marker='o',
                        color='blue',label = etiqueta)
        etiqueta = "("+str(float(x_cero)) + ','
        etiqueta = etiqueta + str(float(y_cero))+")"
        plt.annotate(etiqueta,(x_cero,y_cero), rotation=45)
    # limita radio 1
    graf_ROC.plot(1,0,'o',color='red',
                 label ='radio:'+str(1))
    graf_ROC.axhline(0,color='grey')
    graf_ROC.axvline(0,color='grey')
    graf_ROC.grid()
    graf_ROC.legend()
    graf_ROC.set_xlabel('Re[z]')
    graf_ROC.set_ylabel('Imag[z]')
    untitulo = r'ROC '+f_nombre+'[z]=$'
    untitulo = untitulo+str(sym.latex(Fz))+'$'
    graf_ROC.set_title(untitulo)
    return(fig_zROC)

# a tiene valor a_k
fn = fn.subs(a,a_k) 
Fz = Fz.subs(a,a_k)
# polos y ceros de Fz
polosceros = fcnm.busca_polosceros(Fz)
Q_polos = polosceros['Q_polos']
P_ceros = polosceros['P_ceros']
# estima intervalo para z
z_a = list(Q_polos.keys())
z_a.append(1) # comparar con radio 1
z_a = 2*int(max(z_a))

fig_ROC = graficar_Fz_polos(Fz,Q_polos,P_ceros,
                      muestras=101,f_nombre='X')

fig_Fz = fcnm.graficar_Fs(Fz,Q_polos,P_ceros,
                     -z_a,z_a,muestras=101,
                     f_nombre='X')

# para graficar f[n]
f_n = sym.lambdify(n,fn)
ki  = np.arange(0,m,1)
fi  = f_n(ki)

# entrada x[n]
fig_fn, grafxn = plt.subplots()
plt.axvline(0,color='grey')
plt.stem(ki,fi)
plt.grid()
plt.xlabel('n')
plt.ylabel('x[n]')
etiqueta = r'x[n]= $'+str(sym.latex(fn))+'$'
plt.title(etiqueta)

plt.show()

Referencia: The z-transform.dynamics-and-control. https://dynamics-and-control.readthedocs.io/en/latest/1_Dynamics/9_Sampled_systems/The%20z%20transform.html