1.9 Señales de Energía y Potencia

Señal de Energía

Referencia: Lathi 1.1-1 p65, Hsu 1.2.G p5

Una señal de energía tiene energía finita. En general toda señal en el sentido práctico tiene duración finita, por lo que la energía es finita.

La energía se define como:

E=\int_{-\infty}^{\infty} x^2(t) dt

o de una forma más general incluyendo señales de tipo compleja:

E=\int_{-\infty}^{\infty} |x(t)|^2 dt

No se considera solo como energía el área bajo la curva, o integral de la señal, debido a que puede contener áreas de signo negativo que pueden cancelar la media. El cuadrado de la señal será siempre positivo.

La señal tiene que ser de tipo finita para que la medida tenga significado.

Una condición necesaria para que la señal sea finita es que su amplitud → 0 cuando |t|→ ∞. En cualquier otro caso la integral no converge.

Para una señal discreta:

E=\sum_{n=-\infty}^{\infty} | x[n] |^2

Ejemplo de señal de Energía

Un ejemplo de señal de Energía es un audio limitado en el tiempo, pues su amplitud tiende a 0 cuando |t|→ ∞.

Usando el mismo archivo de audio del ejercicio de señales analógicas y digitales:

Alarm01.wav

Recuerde que el archivo de audio.wav debe estar en el mismo directorio de trabajo que el archivo algoritmo.py.

señal de audio ejemplo

El audio mostrado es una señal limitada en el tiempo, por lo que es posible calcular su energía usando la formula descrita.

Referencia: Archivos de Audio.wav – Abrir, extraer una porción en CCPG1001 Fundamentos de programación

para procesar el archivo, las instrucciones en Python son:

# Señales de Energía y Potencia
import numpy as np
import matplotlib.pyplot as plt
import scipy.io.wavfile as waves

# INGRESO
# archivo = input('archivo de audio: ')
archivo = 'Alarm01.wav'

# PROCEDIMIENTO
muestreo, sonido = waves.read(archivo)
muestra = len(sonido)
dt = 1/muestreo
t = np.arange(0,muestra*dt,dt)
uncanal = sonido[:,0]

# SALIDA - Observación intermedia
plt.plot(t,uncanal)
plt.xlabel('t segundos')
plt.ylabel('sonido(t)')
plt.show()

Integración numérica de muestras

En el caso de las muestras disponibles de audio, las muestras estan igualmente espaciadas, se puede integrar usando la regla de Simpson´s integrate.simps(valores,t) para obtener un estimado de alta precisión.

Para desarrollar el tema de integración nuérica puede revisar el tema en Métodos numéricos en el siguiente enlace:  Unidad 05 Integración y Diferenciación Numérica

import scipy.integrate as integrate

# cuadrado de la señal para el integral de energía
cuadrado = uncanal**2

#integrando a partir de muestras de la señal
energia = integrate.simps(cuadrado,t)

# SALIDA
print(' La energía del audio es: ',energia)
print('\n revisando el canal y sus cuadrados')
print(uncanal[2500:2510])
print(cuadrado[2500:2510])
 La energía del audio es:  3827.5753288
 revisando el canal y sus cuadrados
[-16  -1   8  -3  -8   4  11  -1  -4  10]
[256   1  64   9  64  16 121   1  16 100]

Señal de Potencia

Si en x(t) la amplitud no tiende → 0 al mismo tiempo que |t|→ ∞, la energia de la señal será infinita.

Una mejor medida de la señal en este caso es promedio de energia en el un intervalo de tiempo T, si és periódica, existe T.

La señal de potencia se define como:

P_x =\lim_{T \to \infty}\frac{1}{T} \int_{-T/2}^{T/2} | x(t) |^2 dt

y para una señal discreta:

P =\lim_{N \to \infty}\frac{1}{2N+1} \sum_{n=-N}^{N} | x[n] |^2

Ejemplo: potencia de una señal

Considere una señal periódica conocida sin(), integrando dentro de un periodo podemos calcular la energía y luego la potencia.

# Señales de Energía y Potencia
import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate as integrate

# INGRESO - Parámetros
w  = 1
fx = lambda t: np.sin(w*t)
a  = 0
b  = 2*np.pi # un periodo T
dte = 0.005

# PROCEDIMIENTO
T  = 2*np.pi/w
te = np.arange(a,b,dte)
xe = fx(te)

# energía en un periodo
cuadradoxe = xe**2
energiaxe  = integrate.simps(cuadradoxe,te)

# potencia en un periodo
potenciaxe = (1/T)*energiaxe

# SALIDA
print('la energia de xe es: ',energiaxe)
print('la potencia de xe es: ',potenciaxe)
# gráfica
plt.plot(te,xe,label='xe')
plt.fill_between(te,0,cuadradoxe,color='lightgreen')
plt.plot(te,cuadradoxe,'g--', label='xe^2')
plt.xlabel('t')
plt.legend()
plt.show()
la energia de xe es:  3.14159264282
la potencia de xe es:  0.499999998285

señal al cuadrado para energia y potencia

Para revisar los resultados, realizamos el cáculo de potencia haciendo x(t)=sin(t)

P_x =\lim_{T \to \infty}\frac{1}{T} \int_{-T/2}^{T/2} | x(t) |^2 dt

se tiene que:

=\frac{1}{2\pi} \int_{0}^{2\pi} | sin(t) |^2 dt = \frac{1}{2\pi} \int_{0}^{2\pi} \Big[ \frac{1}{2}-\frac{cos(2t)}{2}\Big] dt =\frac{1}{4\pi} \int_{0}^{2\pi} \Big[ 1-{cos(2t)}\Big] dt =\frac{1}{4\pi} \Big[\int_{0}^{2\pi} 1 dt - \int_{0}^{2\pi}{cos(2t)} \Big]dt =\frac{1}{4\pi} \Big[t \Big|_0^{2\pi} \ - \frac{sin(2x)}{2}\Big|_0^{2\pi} \ \Big] =\frac{1}{4\pi}\Big[(2\pi-0)- (sin(2\pi)-sin(0)) \Big] = \frac{1}{2}

que es el resultado de potencia obtenido usando Python.

Tarea

Realice el mismo cálculo para la energía de la señal del ejemplo anterior.

1.8 Señales con desplazamiento o escalamiento en tiempo

Referencia: Oppenheim 1.2.1 p8 pdf39, Lathi 1.2-1 p71

Desplazamiento en tiempo

Una señal x(t) que se retrasa por k segundos se representa como una versión desplazada hacia la derecha el eje t.

Es decir:

\phi (t+k)= x(t)

o de otra forma:

\phi (t)= x(t-k)

se podrá observar entonces que el signo determina el desplazamiento hacia:

  • la derecha si se resta k
  • la izquierda si se suma k

Para mostrar las reglas, se tiene el siguiente ejemplo, usando como señal

x(t)=sen(t)

señal desplazada en tiempo

Instrucciones en Python

# Señales- Operaciones
import numpy as np
import matplotlib.pyplot as plt

# INGRESO
w  = 1
fx = lambda t: np.sin(w*t)
k  = 1  # desplazamiento

# intervalo de tiempo [a,b)
a  = -8
b  = 8
dt = 0.1

# PROCEDIMIENTO
ti = np.arange(a,b,dt)

senal     = fx(ti)
derecha   = fx(ti-k)
izquierda = fx(ti+k)

# SALIDA
plt.figure(1)
plt.plot(ti,senal,label='x(t)')

plt.plot(ti,derecha,
         label='derecha : x(t-k)',
         linestyle='dashed')
plt.plot(ti,izquierda,
         label='izquierda: x(t+k)',
         linestyle='dashed')

plt.axvline(0, color='gray')
plt.axhline(0, color='gray')
plt.xlabel('t')
plt.legend(loc='lower left')
plt.grid()

plt.show()

Escalamiento en tiempo

La compresión o expansión de la señal en el tiempo es conocida como escalamiento en el tiempo.

Considere la señal x(t) afectada en el tiempo por un factor de 2.
Se encuentra que:

\phi\Big(\frac{t}{2}\Big)=x(t) \phi(t)=x(2t)

siguiendo con la señal del ejercicio anterior

x(t) = sin(t)

señal expande o comprime en tiempo

# Escalamiento en tiempo
factor = 2
expande  = fx(ti/factor)
comprime = fx(factor*ti)

# GRAFICA expande o comprime
plt.figure(2)
plt.plot(ti,senal,label='x(t)')
plt.plot(ti,expande,
         label='expande=x(t/factor)',
         linestyle='dashed')
plt.plot(ti,comprime,
         label='comprime=x(t*factor)',
         linestyle='dashed')
plt.axvline(0, color='gray')
plt.axhline(0, color='gray')
plt.xlabel('t')
plt.legend(loc='lower left')
plt.grid()

plt.show()

Inversión en tiempo

Si la función resultante es x(-t), la señal x(t) se invierte rotando sobre el eje de las ordenadas (vertical).

Observe el resultado de la ecuacion de ejemplo:

señal inversion en tiempo

# inversion en tiempo
espejo = fx(-ti)

# SALIDA
plt.figure(3)
plt.plot(ti,senal,label='x(t)')
plt.plot(ti,espejo,
         label='espejo=x(-t)',
         linestyle='dashed')
plt.axvline(0, color='gray')
plt.axhline(0, color='gray')
plt.xlabel('t')
plt.legend(loc='lower left')
plt.grid()

plt.show()

Modelo general

En resumen, el efecto de transformar la variable independiente de una señal x(t) para obtener la señal modificada es de la forma:

x(at+b)

Con la transformación, la variable independiente conserva la forma de x(t). La señal puede ser:

  • alargada linealmente cuando |a| < 1 ,
  • comprimida si |a| > 1,
  • invertida en el tiempo si a < 0, y
  • desplazada en el tiempo si b es diferente de cero.
    • siendo desplazada a la derecha si se resta el valor de |b|
    • siendo desplazada a la izquierda si se suma el valor de |b|

Desplazamiento en tiempo

solo de un click y observe por un minuto el siguiente video sobre el desplazamiento en el tiempo (delay) en una guitarra.

1.7.1 Señales – Exponencial compleja

Referencia: Lathi 1.4-3 p89, Hsu 1.3.C p9, Oppenheim 1.3.1 p15 pdf46.

Exponencial est

Otra función importante en señales y sistemas es la señal est, donde s es en general de tipo compleja:

s = \sigma + j \omega

lo que convierte:

e^{st} =e^{( \sigma + j \omega)t} = e^{\sigma t} e^{j \omega t} e^{st} =e^{\sigma t} \Big( \cos (\omega t) + j \sin (\omega t)\Big)

dado que la conjugada s* = σ – jω

e^{s^* t} =e^{( \sigma - j \omega)t} = e^{\sigma t} e^{-j \omega t} e^{s^* t} =e^{\sigma t} \Big( \cos (\omega t) - j \sin (\omega t)\Big)

por lo que sumando las ecuaciones resultantes anteriores:

e^{\sigma t} cos(\omega t) = \frac{1}{2}\Big( e^{st} + e^{s^{*}t} \Big)

Comparado con la formula de Euler, se muestra que est es una generalización de e.

La función est tiene varias formas que pueden ser:

  1. una constante k = est cuando s=0
  2. una exponencial monótona eσt cuando ω=0 y s=σ
  3. una sinusoide cos (ωt) cuando σ=0 y s=±jω
  4. una sinusoide con amplitud exponenial  eσt cos (ωt) cuando s=σ ±jω

Desarrollamos la gráfica del primer caso en Python, a partir de la cual repetimos el proceso para analizas los demas casos.

# Señales modelo varias
import numpy as np
import matplotlib.pyplot as plt

# INGRESO
senal = lambda s,t: np.exp(s*t)
sigma = 0  # s = 0 +0j
omega = 0

a  = -5 # intervalo de tiempo [a,b)
b  = 5
dt = 0.1

# PROCEDIMIENTO
ti = np.arange(a, b, dt)
s_i = complex(sigma,omega)
senal_i = senal(s_i,ti)

# SALIDA - gráfica
plt.figure(1)
plt.plot(ti,np.real(senal_i),label='real')
plt.plot(ti,np.imag(senal_i),label='imaginaria')
plt.xlabel('t')
plt.ylabel('x(t)')
plt.legend()
plt.grid()
plt.title('e^('+str(sigma) +' + '+str(omega)+'j)')
plt.show()

A partir de aquí se continúa con la definición de t en el intervalo del ejercicio anterior, por lo que las instrucciones de Python se añaden a continuación de lo anterior.

Un exponencial simple σ>0 ω=0

Para éste caso se modifica en el bloque de ingreso los parámetros de σ=1 y ω=0, con lo que el algoritmo realiza la gráfica presentada.

# un exponencial simple sigma>0 omega=0 
sigma = 1
omega = 0

un exponencial simple σ<0 ω=0

Para éste caso se modifica en el bloque de ingreso los parámetros de σ=-1 y ω=0, con lo que el algoritmo realiza la gráfica presentada.

# un exponencial simple sigma<0 omega=0
sigma = -1
omega = 0

un sinusiode σ=0, ω>0

Para éste caso se modifica en el bloque de ingreso los parámetros de σ=0 y ω=1, con lo que el algoritmo realiza la gráfica presentada.

# un sinusiode sigma=0, omega>0
sigma = 0
omega = 1

un sinusiode σ=0, ω<0

Para éste caso se modifica en el bloque de ingreso los parámetros de σ=0 y ω=-1, con lo que el algoritmo realiza la gráfica presentada.

# un sinusiode sigma=0, omega<0
sigma = 0
omega = -1

un sinusoide con amplitud exponencial σ=0.25, ω>0

# un sinusoide con amplitud exponencial sigma=0.25, omega>0
sigma = 0.25
omega = 4

un sinusoide con amplitud exponencial σ=-0.25, ω>0

# un sinusoide con amplitud exponencial sigma=-0.25, omega>0
sigma = -0.25
omega = 4

1.7 Señales Compuestas

Referencia: Lathi Ejercicio 1.8 p86, Oppenheim ejemplo 1.1 p10, Hsu problema 1.22 p35

Una señal que se compone de varias señales mas simples se puede manejar como un conjunto de instrucciones por bloques.

Para ello, en Python es necesario seleccionar la forma más apropiada para definir cada señal:

  • por bloques def-return
  • en formato simplificado lambda

Un escalón es mas sencillo definirlo en formato de línea. Sin embargo, una señal con más partes se recomendaría realizarla por bloques, definiendo su forma más básica para luego poder realizar cambios de escala o desplazamientos en el tiempo.


Ejemplo 1. Señal compuesta

Referencia: Lathi Ejercicio 1.8 p86

Demuestre que la señal mostrada en la figura (en libro y al final) puede ser descrita como:

x(t) = (t-1)\mu(t-1) - (t-2)\mu(t-2) - \mu(t-4)

Instrucciones en python

En el ejercicio se presenta una solución por partes, mostrando que la señal se compone de la «suma» de sus partes. Se utiliza la propiedad de la linealidad para los sistemas.

# Señales modelo varias- ejercicio
import numpy as np
import matplotlib.pyplot as plt

# INGRESO
# u = lambda t: np.piecewise(t, t>=0, [1,0])
u = lambda t: np.heaviside(t,1)

# señal como suma de las partes
x1 = lambda t: (t-1)*u(t-1)
x2 = lambda t: -(t-2)*u(t-2)
x3 = lambda t: - u(t-4)

x = lambda t: x1(t) + x2(t) + x3(t)

# tiempo intervalo de observación
a = -2
b = 8
dt = 0.05

# PROCEDIMIENTO
ti = np.arange(a, b, dt)
xi = x(ti)

# evalua componentes para grafica
x1i = x1(ti)
x2i = x2(ti)
x3i = x3(ti)

# SALIDA - gráfico

plt.figure(1) # componentes
plt.plot(ti, x1i, '--', label='(t-1)u(t-1)')
plt.plot(ti, x2i, '--', label='- (t-2)u(t-2)' )
plt.plot(ti, x3i, '--', label='- u(t-4)')
plt.plot(ti, xi, label='x(t)')
plt.legend()
plt.ylabel('x(t) por partes')
plt.xlabel('t')
plt.grid()

plt.figure(2) # señal compuesta
plt.plot(ti, xi, label='x(t)')
plt.ylabel('x(t)')
plt.xlabel('t')
plt.grid()

plt.show()

Ejemplo 2. Señal compuesta

Referencia: Oppenheim ejemplo 1.1a p.10

Dada la señal x(t) mostrada en la siguiente gráfica, realizar x(t+1), …

Procedemos como en el ejercicio anterior, continuando con el uso de la función escalón μ(t) .

# Señales modelo varias-ejercicio
import numpy as np
import matplotlib.pyplot as plt

# INGRESO
# u = lambda t: np.piecewise(t, t>=0, [1,0])
u = lambda t: np.heaviside(t,1)

# señal como suma de las partes
x1 = lambda t: -(t-1)*u(t-1)
x2 = lambda t: (t-2)*u(t-2)

x = lambda t: u(t) + x1(t) + x2(t)

# tiempo intervalo de observación
a = -2
b = 8
dt = 0.05

# PROCEDIMIENTO
ti = np.arange(a, b, dt)
xi = x(ti)

# evalua componentes para grafica
x0i = u(ti)
x1i = x1(ti)
x2i = x2(ti)

# SALIDA - gráfico

plt.figure(1) # componentes
plt.plot(ti,x0i, '--', label='u(t)')
plt.plot(ti,x1i, '--', label='-(t-1)*u(t-1)')
plt.plot(ti,x2i, '--', label='(t-2)*u(t-2)')
plt.plot(ti,xi, label='x(t)')
plt.legend()
plt.ylabel('x(t) por partes')
plt.xlabel('t')
plt.grid()

plt.figure(2) # señal compuesta
plt.plot(ti, xi, label='x(t)')
plt.ylabel('x(t)')
plt.xlabel('t')
plt.grid()

plt.show()

el resultado de la señal compuesta se observa en la gráfica


Ejercicio3. Señal con desplazamiento y escala

Referencia: Oppenheim ejemplo 1.1b p.10

Continuando con el ejercicio anterior, realizar la gráfica:

2x(t+1)

Para el ejercicio, se define el punto donde se desplaza la señal, y la escala para la amplitud. Para observar los cambios se grafica el desplazamiento y luego el cambio de escala.

# INGRESO 
desplaza = -1
escala = 2

xd_i = x(ti-desplaza)
yi = escala*x(ti-desplaza)

# salida - gráfico
plt.figure(4)
plt.plot(ti, xi, '--' , label='x(t)')
plt.plot(ti, xd_i, '-.', label='x(t-desplaza)')
plt.plot(ti, yi, label='escala*x(t-desplaza)')
plt.xlabel('t')
plt.legend()
plt.grid()

plt.show()


Tarea

Referencia: Oppenheim ejemplo 1.1a pdf/p.10

A partir de la seña x(t) del ejercicio anterior, realice el ejercicio para obtener las gráficas:

  • x(-t+1)
  • x(3t/2)
  • x(3t/2 +1)

Otros ejercicios

Referencia: Hsu problema 1.22 p35

1.6 Señales Escalón μ(t) e Impulso unitario δ(t)

Referencia: Lathi 1.4.1 p83, Hsu 1.3 p6, Oppenheim 1.4 p30 pdf61

1. Escalón unitario μ(t)

En muchos de los temas de curso se usan sistemas causales que inician en t=0. La función que describe éste comporamiento es μ(t) descrita como:

\mu(t)= \begin{cases} 1, & t\geq 0 \\ 0, & t<0\end{cases}

Algunas señales pueden convenientemente ser descritas usando términos de una función μ(t) como se muestra en los siguientes ejemplos.

Instrucciones en Python

La función μ(t) se puede describir con la np.piecewise()o np.heaviside(t,1)

# Señales modelo varias
import numpy as np
import matplotlib.pyplot as plt

# INGRESO
#u = lambda t: np.piecewise(t,t>=0,[1,0])
u = lambda t: np.heaviside(t,1)

a = -10
b = 10
dt = 0.1

# PROCEDIMIENTO
ti  = np.arange(a, b, dt)
u0_i = u(ti)

# SALIDA - GRAFICA
print('t:',ti)
print('t:',u0_i)

# grafica
plt.figure(1)
plt.plot(ti,u0_i)

plt.xlabel('t')
plt.ylabel('escalon u(t)')
plt.margins(dt)
plt.grid()
plt.show()

Señal Causal con Escalón unitario

Para convertir una señal cualquiera a causal, que inicie en t=0, se multiplica la señal por μ(t).

Por ejemplo, x(t)=e-αt se puede convertir a una señal causal si se escribe como:

x(t) = e^{-\alpha t} \mu(t)

Para mostrar lo indicado y considerando α=1 tenemos que:

# señal a causal
x = lambda t: np.exp(-t)*u(t)
xi = x(ti)

# SALIDA - GRAFICA
plt.figure(2)
plt.plot(ti,xi)

plt.xlabel('t')
plt.ylabel('x(t)u(t)')
plt.margins(dt)
plt.grid()
plt.show()

La función escalón unitario tambien permite realizar descripciones matematicas sobre diferentes segmentos del tiempo.

Señal Rectangular

Por ejemplo, una señal rectangular se puede representar como la suma de dos señales μ(t) desplazadas:

x(t) = \mu (t-2) - \mu (t-4)

# Rectangular como u(t-2)-u(t-4)
# u2 = lambda t: np.piecewise(t,t>=2,[1,0])
# u4 = lambda t: np.piecewise(t,t>=4,[1,0])

u2 = lambda t: u(t-2)
u4 = lambda t: u(t-4)
rectangular = lambda t:u2(t) - u4(t)
rect_i = rectangular(ti)

# SALIDA - GRAFICA
plt.figure(3)
plt.plot(ti,rect_i)

plt.xlabel('t')
plt.ylabel('rectangular(t)')
plt.margins(dt)
plt.grid()
plt.show()

2. Impulso unitario δ(t)

El impulso unitario δ(t) es una función definida primero por Paul Dirac de la forma:

\delta(t)=0,t\neq 0 \int_{-\infty}^{\infty} \delta(t) dt = 1

Se puede ver al impulso como un pulso rectangular muy pequeño de área unitaria. El ancho del pulso rectangular es muy pequeño.

Siguiendo el concepto, se puede representar como:

Instrucciones en Python

# Señales impulso unitario
import numpy as np
import matplotlib.pyplot as plt

# INGRESO
# u = lambda t: np.piecewise(t,t>=0,[1,0])
u = lambda t: np.heaviside(t,1)

impulso = lambda t,dt: u(t)-u(t-dt)

# intervalo de observación
a = -10
b = 10

dt = 0.1  # tamaño de paso
t0 = 0    # punto de impulso

# PROCEDIMIENTO
ti  = np.arange(a, b, dt)
impulso_i = impulso(ti,dt)

# SALIDA - GRAFICA
# plt.plot(ti,impulso_i)
plt.stem(ti,impulso_i)
plt.xlabel('t')
plt.ylabel('impulso()')
plt.grid()
plt.show()

Otra forma de representar el impulso unitario es:

\delta(t)= \begin{cases} 1, & t = 0 \\ 0, & t \neq 0\end{cases}

que como instrucción es,

impulso = lambda t,t0,tolera: 1*(np.abs(t-t0)<=tolera)
t0 = 0  # punto de impulso
tolera = 1e-10 # casicero

Para la gráfica también se usa stem(x,y):

# SALIDA - GRAFICA
plt.figure(5)
plt.stem(ti,impulso_i)

plt.margins(dt)
plt.xlabel('t')
plt.ylabel('impulso(t)')
plt.grid()
plt.show()

También se puede usar la librería scipy para tener un impulso más general:

https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.unit_impulse.html

hay que importar la libreria scipy para ese caso.

1.5 Señales Pares e Impares

Referencia: Lathi 1.5 p92, Oppenheim 1.2.3 p13 pdf44, Hsu 1.2.E p3

Señales Pares

Una señal x(t) ó x[n] es par si se «refleja» en el eje vertical u ordenadas.

x(t) = x(-t) x[n] = x[-n]

La señal tiene los mismos valores para el lado positivo o negativo de |t|.

Es como si se aplicara el valor absoluto de t antes de hacerlo en la ecuación.

Señales Impares

Una señal x(t) ó x[n] es impar si se cumple que:

x(t) = -x(-t) x[n] = -x[-n]

Una señal impar debe ser necesariamente 0 en t=0 o n=0.


1. Ejemplo. grafica de señal par con Python

Un señal par conocida es cos(t)

Para observar mejor, se marcará el área que genera la función dentro de un periodo centrado en el origen.

Para ilustrar mejor el concepto se reutiliza los ejemplos anteriores de señales periódicas.

Se inicializa los parámetros para:

  • el periodo T de una señal
  • el número m de periodos que se observarán de la señal, donde m debe ser un número par.
  • El punto de inicio t0 para el eje horizontal se puede calcular a partir de T y m, dado que se extiende hacia cada lado del eje vertical, t0 al encontrarse a la izquierda del eje vertical tiene signo negativo.
  • El punto de final tn para tendrá el signo positivo de t0
  • los tramos por periodo de la señal a observar, deben ser un número 2k, donde k es un número entero.
# Señales pares e impares
import numpy as np
import matplotlib.pyplot as plt

# INGRESO parámetros
T  = 2*np.pi
f  = 1/T
w  = 2*np.pi*f
fx = lambda t: np.cos(w*t)

m  = 2        # incluir m periodos en grafica
t0 = -(m/2)*T # usa lado negativo de abscisas
tramos = 32   # tramos por periodo 2**k, siendo k entero

Para observar mejor la gráfica, se marcará el área que genera la señal dentro de un periodo centrado en el origen.

La cantidad de muestras depende de cúantos periodos m de la señal se quieran observar. Se necesitan tantas muestras como tramos de cada lado, incluuendo la muestra del origen (m*tramos+1).

# PROCEDIMIENTO
tn = -t0 # vector de tiempo
muestras = m*tramos+1
ti = np.linspace(t0,tn,muestras)
# dt = ti[1]-ti[0]
dt = (tn-t0)/(tramos*m)

senal = fx(ti)

# marcar un periodo en [desde, hasta]
desde = -T/2
hasta = desde + T + dt
tperiodo = np.arange(desde,hasta,dt)
periodo = fx(tperiodo)

Se marca un periodo comprendido en: [-T/2,T/2], sombreando alrededor de t=0. Para destacar el ejer vertical se usa el color rojo.

# SALIDA
# Gráficas
plt.plot(ti,senal)
plt.xlabel('t')
plt.ylabel('señal x(t)')
plt.grid(True)

# marcar un periodo
plt.title('Señal PAR')
plt.fill_between(tperiodo,0,periodo,
                 color='lightgreen')
plt.axvline(x=0, color='red')
plt.show()

2. Ejemplo. gráfica de señal impar con Python

En el ejemplo se usará una señal par como el sin(). Se utiliza las instrucciones del algoritmo anterior, modificando la señal f(x) en el bloque de ingreso

fx = lambda t: np.sin(w*t)

y el título de la gráfica

plt.title('Señal IMPAR')

Las instrucciones en Python para señales pares e impares son:

# Señales pares e impares
import numpy as np
import matplotlib.pyplot as plt

# INGRESO parámetros
T  = 2*np.pi
f  = 1/T
w  = 2*np.pi*f
fx = lambda t: np.cos(w*t)

m  = 2        # incluir m periodos en grafica
t0 = -(m/2)*T # usa lado negativo de abscisas
tramos = 32    # tramos por periodo 2**k, siendo k entero

# PROCEDIMIENTO
tn = -t0  # vector de tiempo
muestras = m*tramos+1
ti = np.linspace(t0,tn,muestras)
# dt = ti[1]-ti[0]
dt = (tn-t0)/(tramos*m)

senal = fx(ti)

# marcar un periodo en [desde, hasta]
desde = -T/2
hasta = desde + T + dt
tperiodo = np.arange(desde,hasta,dt)
periodo  = fx(tperiodo)

# SALIDA
# Gráficas
plt.plot(ti,senal)
plt.xlabel('t')
plt.ylabel('señal x(t)')
plt.grid(True)

# marcar un periodo
plt.title('Señal PAR')
plt.fill_between(tperiodo,0,periodo,
                 color='lightgreen')
plt.axvline(x=0, color='red')
plt.show()

Tarea

probar con otras funciones tales como:

  • t
  • |t|
  • t2
  • t3
  • |- et|

nota: el valor absoluto en python para t se escribe como abs(t), o usando numpy np.abs(t)

1.4 Señales Periódicas y No periódicas

Señal Periódica

Referencia: Oppenheim 1.2.2 p11 pdf42, Hsu Cap1.2,F p4, Lathi 1.3.3. p79

Una señal periódica contínua tiene la propiedad que su valor se repite luego de un desplazamiento de tiempo T.

x(t) = x(t+T)

señal periodica vs no periódica

El valor de T es conocido como el periodo de la señal.

La relación entre el periodo T y la frecuencia f se da por la ecuacion:

f = \frac{1}{T} \text{, en Hz} \omega = 2 \pi f = \frac{2 \pi}{T} \text{, en rad/s}

otra forma de escribir la ecuación es:

x(t) = x(t + mT)

para cualquier valor de t y cualquier número entero m. El periodo fundamental T0 de x(t) es el valor positivo más pequeño que hace posible la ecuación descrita.

señal periódica ejemplo

Instrucciones en Python

Las instrucciones son semejantes a graficar señales contínuas. Para el ejemplo se analiza la señal coseno(t), con periodo T=2π para un en un intervalo de dos periodos m=2 y 51 muestras. Se crea el vector ti para el intervalo de observación y se calcula la señal.

# Señales periodicas
import numpy as np
import matplotlib.pyplot as plt

# INGRESO
T = 2*np.pi
f = 1/T
w = 2*np.pi*f
fx = lambda t: np.cos(w*t)
t0 = 0   # intervalo tiempo [t0,tn]
m  = 2   # incluir m periodos en grafica
muestras  = 51
desde = T/4 # marcar periodo [desde,hasta]

# PROCEDIMIENTO
tn = m*T   # vector de tiempo
ti  = np.linspace(t0,tn,muestras)
# dt = ti[1]-ti[0]
dt = (tn-t0)/(muestras-1)

senal = fx(ti)

# marcar un periodo en [desde, hasta]
hasta = desde + T + dt
tperiodo = np.arange(desde,hasta,dt)
periodo  = fx(tperiodo)

La gráfica se conforma de dos partes:

  • la señal calculada
  • la señal marcada en un periodo
# SALIDA
# Grafica
plt.plot(ti,senal)
plt.xlabel('t')
plt.ylabel('señal x(t)')
plt.grid()
plt.axhline(0, color='gray')
plt.axvline(0, color='gray')

# marcar un periodo
plt.title('marcando un periodo')
plt.fill_between(tperiodo,0, periodo,facecolor='green')
plt.show()

Señal periódica discreta

Se define semejante a las señales periódicas contínuas como una secuencia discreta en el tiempo x[n]. La señal es periódica con periodo N si existe un número entero positivo para el que:

x[n + N] = x[n] \text{, para todo n} x[n + mN] = x[n]

para todo n y cualquier entero m

El periodo fundamental N0 de x[n] es el valor positivo mas pequeño para que se cumpla la ecuación en la secuencia de datos de la señal.

Como ejemplo se usa una señal muestreada del coseno:

señal periódica digital

Instrucciones en Python

Semejante al algoritmo del ejercicio anterior, se genera la nueva gráfica en forma discreta.

# Señales periodicas Discretas
import numpy as np
import matplotlib.pyplot as plt

# INGRESO parametros
N  = 8
w  = 2*np.pi/N
fx = lambda n: np.cos(w*n)
n0 = 0   # intervalo [n0,n0+muestras]
m  = 4   # incluir m periodos en grafica

# PROCEDIMIENTO
muestras = m*N+1
ni = np.arange(n0,n0+muestras,1)
senal = fx(ni)

# SALIDA
# Grafica
plt.stem(ni,senal)
plt.xlabel('n')
plt.ylabel('x[n]')
plt.grid()
plt.show()

Señal No periódica

En éste caso, los valores de la señal no se repiten para ningun valor de T.

También para algunos problemas se considera que T → ∞.

Un ejemplo del tipo de señal es: x(t)=t^2

señal no periódica o aperiódica

Instrucciones en Python

Usando lo realizado para señales periódicas contínuas, cambiando la funcion fx y quitando las marcas de un periodo.

# Señales NO periodicas contínuas
import numpy as np
import matplotlib.pyplot as plt

# INGRESO
T = 2*np.pi
f = 1/T
w = 2*np.pi*f
fx = lambda t: t**2
t0 = 0   # intervalo tiempo [t0,tn]
m  = 2   # incluir m periodos en grafica
muestras  = 51

# PROCEDIMIENTO
tn = m*T   # vector de tiempo
ti  = np.linspace(t0,tn,muestras)

senal = fx(ti)

# SALIDA
# Grafica
plt.plot(ti,senal)
plt.xlabel('t')
plt.ylabel('señal x(t)')
plt.grid()
plt.axhline(0, color='gray')
plt.axvline(0, color='gray')
plt.show()

Para el caso de señal discreta, considere el punto de partida del algoritmo correspondiente y modifique:

yn = lambda n: n**2

# SALIDA - Gráfica
plt.stem(ni,yi)
plt.xlabel('n')
plt.ylabel('y[n]')
plt.show()

señal aperiódica digital


Tarea

Pruebe con otras funciones contínuas para x(t) como:

  • t^3
  • e^t
  • \frac{1}{t}

en Python, el exponente se escribe como: t**3 y en la otra función np.exp(t)

Realizar el mismo paso para sus formas discretas.

1.3 Señales Analógicas y Digitales

Referencia: Lathi 1.3.2 p78, Hsu 1.2.B p2

señal analógica vs digital


1. Señales Analógicas

Una señal se clasifica como analógica cuando su amplitud puede tomar un infinito numero de valores en un rango contínuo de tiempo.

Por ejemplo, una señal de sonido como la del archivo:

Alarm01.wav

Nota: Descargue el archivo use un programa como windows media player para escuchar su contenido.

Instrucciones en Python

Para observar en una gráfica la señal del archivo de sonido anterior, a las librerías numéricas y gráficas, se añade la librería SciPy (scientific Python) que dispone de instrucciones para lecturas de archivos de audio en formato .wav

Nota: Si usa WinPython la librería viene incluida, en otro caso se puede instalar con PIP install scipy en la línea de comandos del sistema.

En el algoritmo se define el nombre del archivo.wav a usar, y mediante la instrucción waves.read() se obtienen los datos de velocidad de muestreo y el arreglo de sonido.

# Señales analógicas
import numpy as np
import matplotlib.pyplot as plt
import scipy.io.wavfile as waves

# INGRESO
# archivo = input('archivo de audio: ')
archivo = 'Alarm01.wav'
muestreo, sonido = waves.read(archivo)

# SALIDA - Observacion intermedia
print('frecuencia de muestreo: ', muestreo)
print('dimensiones de matriz: ', np.shape(sonido))
print('datos de sonido: ')
print(sonido)

el resultado del algoritmo muestra:

frecuencia de muestreo:  22050
dimensiones de matriz:  (122868, 2)
datos de sonido: 
[[0 0]
 [0 0]
 [0 0]
 ..., 
 [0 0]
 [0 0]
 [0 0]]

En caso de requerir revisar más detalles sobre audio.wav se pueden encontrar en el siguiente enlace.

Archivos de Audio.wav – Abrir, extraer una porción

Con los resultados mostrados, se observa que:

  • la señal de audio tiene frecuencia de muestreo de 22050 Hz
  • Las dimensiones de la matriz sonido (122868,2) indican que es de tipo estéreo por usar dos columnas,
  • el valor de 122868 corresponde a la cantidad de muestras por canal,
  • Los índices para seleccionar un canal son 0 ó 1 interpretado como canal izquierdo o derecho.

Para observar la forma del sonido se extrae el canal 0 y solo un segmento o intervalo de tiempo [inicia,termina).

Para observar otros segmentos la señal de audio cambie los valores de  [inicia,termina), añadiendo las instrucciones siguientes:

# segmento de tiempo
canal  = 0
inicia = 2600
termina = 2720

# Extrae el segmento desde sonido
dt = 1/muestreo
ti  = np.arange(inicia*dt,termina*dt,dt)
muestras = len(ti)
segmento = sonido[inicia:inicia+muestras, canal]

#SALIDA
plt.plot(ti,segmento)
plt.xlabel('t segundos')
plt.ylabel('sonido(t)')
plt.show()


2. Señales Digitales

Una señal se clasifica como digital cuando la amplitud  puede tomar solo un número finito de valores, para un número finito de muestras en el tiempo.

Siguiendo el ejemplo de la señal de audio, las señales digitales se las asocia con computadoras. Para almacenar una señal de audio, se la cuantifica en amplitud a espacios iguales de tiempo dt.

Por ejemplo, datos del vector segmento del audio del ejercicio anterior muestran el caracter finito, discreto, por muestras de la señal.

# SALIDA - datos del segmento de audio
print(segmento)
[  -36   -52    11  -280  -595  -186   656   800   141
  -237   -53  -246  -910  -739   569  1347   620  -288
  -195   -57  -812 -1229   -37  1419  1183   -51  -348
    47  -424 -1322  -778   955  1531   432  -363   -62
  -123 -1062 -1189   306  1514   910  -172  -224   -57
  -720 -1191  -164  1241  1134    75  -295  -144  -533
 -1035  -367   953  1144   262  -234  -202  -499  -931
  -423   781  1095   344  -152  -174  -491  -916  -440
   739  1088   353  -149  -158  -467  -901  -472   693
  1116   405  -164  -172  -434  -906  -558   608  1139
   478  -159  -181  -370  -870  -655   494  1151   565
  -130  -180  -307  -812  -735   358  1149   666   -95
  -213  -291  -785  -824   214  1143   784   -31  -217
  -249  -727  -888    54]

los datos del segmento de audio, muestran que la señal de audio se almacena como una señal discreta, o digital, por lo que una gráfica más apropiada es:

# grafica segmento de sonido en forma discreta
ni = np.arange(inicia,inicia+muestras,1)
plt.stem(ni,segmento)
plt.xlabel('n')
plt.ylabel('segmento sonido[n]')
plt.show()

Observaciones

Los términos «contínuo en el tiempo» y «discreto en el tiempo» cuantifican la naturaleza de la señal solo en el eje de las abscisas (horizontal).

Los términos «analógicos» y «digitales» cuantifican la amplitud de la señal o eje de las ordenadas (vertical).

Una señal de audio, por su naturaleza es de tipo analógica, que para almacenarla o procesarla en un computador se convierte a digital al cuantificar sus valores de amplitud, de la forma mostrada en el ejercicio.


Tarea

  • cambie los rangos de observación de la señal de audio y repita las gráficas para su forma analógica aproximada (parte 1) y para su forma digital (parte 2)
  • comente sobre el segmento al inicio y final de todo el audio donde los valores de la señal son 0’s

Instrucciones en Python

# Señales analógicas
import numpy as np
import matplotlib.pyplot as plt
import scipy.io.wavfile as waves

# INGRESO
archivo = 'Alarm01.wav'

# segmento de tiempo
canal   = 0
inicia  = 2600
termina = 2720

# PROCEDIMIENTO
muestreo, sonido = waves.read(archivo)

# Extraer el segmento de sonido
dt = 1/muestreo
ti = np.arange(inicia*dt, termina*dt , dt)
muestras = len(ti)
segmento = sonido[inicia: inicia+muestras,canal]

# SALIDA
print('frecuencia de muestreo:', muestreo)
print('dimensiones de sonido: ',np.shape(sonido))
print('datos del sonido:')
print(sonido)

print('segmento:')
print(segmento)

# Grafica
plt.stem(ti,segmento)
plt.xlabel('t segundos')
plt.ylabel('sonido(t)')
plt.show()

1.2 Señales Discretas con Python

Referencia: Oppenheim 1.3.2 fig.1.25 p24, Lathi 1.3.1 p78, Hsu 1.2.A p1

Para una señal discreta en un intervalo desde n0, con m muestras, tamaño de paso 1, se genera una secuencia numérica cuya gráfica es:

\sin [\omega n]

El muestreo para cada valor n se establece en el  intervalo [0, m) , para m muestras y con frecuencia ω = 2π/12 radianes/segundo.

Para el ejercicio se usa m=12

Semejante a las gráficas de señales contínua, el bloque de INICIO añade las librerías de numpy y matplotlib.

El bloque de INGRESO define los valores de los parámetros, la señal f(x) en formato simplificado lambda, con variable independiente n, el punto inicial n0 y el número de muestras m (recuerde contar el cero)

# Señales discretas
import numpy as np
import matplotlib.pyplot as plt

# INGRESO - parámetros
w  = 2*np.pi/12
fx = lambda n: np.sin(w*n)

n0 = 0  # intervalo en un periodo
muestras = 12+1

En el bloque de Procedimiento, los valores discretos de n se almacenan en un vector de tamaño m. La señal se puede crear usando la funcion sin() incluida en numpy.

# PROCEDIMIENTO
# vector ni discreto [n0,n0+muestras]
ni = np.arange(n0,n0+muestras,1)

senal = fx(ni)

Observe que los valores para n corresponden a una secuencia numérica.

El bloque de SALIDA puede mostrar los resultados en forma numérica o gráfica.

# SALIDA
np.set_printoptions(precision=4)
print('n: ')
print(ni)
print('señal x[n]: ')
print(senal)
n: 
[ 0  1  2  3  4  5  6  7  8  9 10 11 12]
señal x[n]: 
[ 0.0000e+00  5.0000e-01  8.6603e-01  1.0000e+00
  8.6603e-01  5.0000e-01  1.2246e-16 -5.0000e-01
 -8.6603e-01 -1.0000e+00 -8.6603e-01 -5.0000e-01
 -2.4493e-16]

Para observar el resultado de la señal, se grafica ni vs señal[n], añadiendo las etiquetas para cada eje, y mostrando el resultado con plt.show().

Se usa la gráfica stem() para obtener en la gráfica el punto y una línea que muestre la magnitud, semejante a las gráficas de los libros de texto.

# Gráficas
plt.stem(ni, senal)

plt.xlabel('n')
plt.ylabel('señal x[n]')
plt.grid()

plt.show()

Tarea

Para ésta sección, se cambiarán los parámetros de n y ω.

  • muestras = 50
  • ω0 = π/4 y ω0 = 15π/8
  • cambiar la función a np.cos()
  • ¿se puede cambiar la amplitud de la señal a 2 y ω0=1/6?

Instrucciones Python

# Señales discretas
import numpy as np
import matplotlib.pyplot as plt

# INGRESO - parámetros
w  = 2*np.pi/12
fx = lambda n: np.sin(w*n)

n0 = 0  # intervalo [n0,n0+muestras]
muestras = 12+1

# PROCEDIMIENTO
# vector n de muestras [n0,n0+muestras]
ni = np.arange(n0,n0+muestras,1)

senal = fx(ni)

# SALIDA
np.set_printoptions(precision=4)
print('n: ')
print(ni)
print('señal x[n]: ')
print(senal)

# Gráficas
plt.stem(ni, senal)
plt.xlabel('n')
plt.ylabel('señal x[n]')
plt.grid()
plt.show()

1.1 Señales Contínuas con Python

Referencia: Oppenheim 1.1 p1 pdf32, Lathi 1.3.1 p78, Hsu 1.2.A p1

Un ejemplo clásico de una señal contínua es una de forma sinusoidal como la mostrada en la figura.

\sin (\omega t)

La función de la señal en el tiempo se define en el intervalo [t0, tn) para n tramos y una frecuencia angular ω en radianes/segundo. Recordar que ω = 2πf, siendo f la frecuencia en Hz o unidades de 1/s, por si requiere hacer la conversión de frecuencias.

Para facilitar la tarea, en Python se usan las librerias para el manejo de vectores y gráficas:

    • vectores – numpy
    • gráficas – matplotlib.pyplot

Un resumen de gráficas en 2D de línea se presenta también en el curso MATG1052 de métodos numéricos. Tambien se dispone de un video tutorial: U1T2 Funciones y Gráficas .

Inicio e Ingreso de parámetros

En el bloque de INICIO se añaden las librerias numpy y matplotlib. Luego se definen los parámetros de la señal a usar y se describe la señal con la expresión matemática en su forma simplificada lambda.

Se añade el intervalo de observación y el número de muestras para la gráfica.

# Señales continuas
import numpy as np
import matplotlib.pyplot as plt

# INGRESO
w  = 1
fx = lambda t: np.sin(w*t)

t0 = 0   # intervalo [t0,tn]
tn = 2*np.pi
muestras = 51

Procedimiento – calcular valores

Para la gráfica, las muestras de tiempo t se almacenan en un vector de tamaño n. Entre cada valor de t existe una diferencia dt deteminada por n.

# PROCEDIMIENTO
# vector de tiempo
ti = np.linspace(t0,tn,muestras)

# señal
senal = fx(ti)

Salida – valores y gráfica

El resultado puede ser observado de dos formas:
– mostrando sus valores o
– sus gráficas.

Se presentan las dos opciones a escoger.

# SALIDA
np.set_printoptions(precision = 4)
print('tiempo: ')
print(ti)
print('señal: x(t) ')
print(senal)
tiempo: 
[0.     0.1257 0.2513 0.377  0.5027 0.6283 0.754 
 0.8796 1.0053 1.131  1.2566 1.3823 1.508  1.6336
 1.7593 1.885  2.0106 2.1363 2.2619 2.3876 2.5133
 2.6389 2.7646 2.8903 3.0159 3.1416 3.2673 3.3929
 3.5186 3.6442 3.7699 3.8956 4.0212 4.1469 4.2726
 4.3982 4.5239 4.6496 4.7752 4.9009 5.0265 5.1522
 5.2779 5.4035 5.5292 5.6549 5.7805 5.9062 6.0319
 6.1575]
señal: x(t) 
[ 0.0000e+00  1.2533e-01  2.4869e-01  3.6812e-01
  4.8175e-01  5.8779e-01  6.8455e-01  7.7051e-01
  8.4433e-01  9.0483e-01  9.5106e-01  9.8229e-01
  9.9803e-01  9.9803e-01  9.8229e-01  9.5106e-01
  9.0483e-01  8.4433e-01  7.7051e-01  6.8455e-01
  5.8779e-01  4.8175e-01  3.6812e-01  2.4869e-01
  1.2533e-01 -3.2162e-16 -1.2533e-01 -2.4869e-01
 -3.6812e-01 -4.8175e-01 -5.8779e-01 -6.8455e-01
 -7.7051e-01 -8.4433e-01 -9.0483e-01 -9.5106e-01
 -9.8229e-01 -9.9803e-01 -9.9803e-01 -9.8229e-01
 -9.5106e-01 -9.0483e-01 -8.4433e-01 -7.7051e-01
 -6.8455e-01 -5.8779e-01 -4.8175e-01 -3.6812e-01
 -2.4869e-01 -1.2533e-01]

Para observar el resultado de la señal, se grafica t vs señal. Para mejor identificación de ejes, se añade las etiquetas y las líneas de referencia.

# Gráfica
plt.plot(ti,senal)
plt.axhline(0, color='gray')
plt.axvline(0, color='gray')
plt.xlabel('t')
plt.ylabel('señal x(t)')
plt.grid()
plt.show()


Tarea

Para ésta sección, se cambiarán los parámetros de tiempo.

  • tn=8π
  • ω=2
  • cambiar la función a np.cos()
  • ¿se puede cambiar la amplitud de la señal a 4?

Instrucciones en Python

# Señales continuas
import numpy as np
import matplotlib.pyplot as plt

# INGRESO
w  = 1
fx = lambda t: np.sin(w*t)

t0 = 0   # intervalo [t0,tn]
tn = 2*np.pi
muestras = 51

# PROCEDIMIENTO
# vector de tiempo
ti = np.linspace(t0,tn,muestras)

# señal
senal = fx(ti)

# SALIDA
np.set_printoptions(precision = 4)
print('tiempo: ')
print(ti)
print('señal: x(t) ')
print(senal)

# Gráfica
plt.plot(ti,senal)
plt.axhline(0, color='gray')
plt.axvline(0, color='gray')
plt.xlabel('t')
plt.ylabel('señal x(t)')
plt.grid()
plt.show()