pmf – Modulación QPSK

QPSK (Quadrature Phase-Shift Keying)

Este esquema de modulación es conocido también como Quaternary PSK (PSK Cuaternaria), Quadriphase PSK (PSK Cuadrafásica).

Esta modulación digital es representada en el diagrama de constelación por cuatro puntos equidistantes del origen de coordenadas.

Con cuatro fases, QPSK puede codificar dos bits por cada símbolo.

Respecto a un ancho de banda predeterminado, la ventaja de QPSK sobre BPSK está que con el primero se transmite el doble de la velocidad de datos en un ancho de banda determinado en comparación con BPSK, usando la misma tasa de error.

En el caso de la canción procesada en BPSK, se cargan una cantidad de datos que se pueden procesar con la mitad de símbolos, enviando la información por pares.

La pmf del proceso QPSK será:


Resultados del algoritmo:

datos cargados:  8595119
símbolos procesados:  4297559
[[ 539083       0 1580668]
 [      1       0       0]
 [1638724       0  539083]]
pmf[x,y]
[[  1.25439348e-01   0.00000000e+00   3.67806003e-01]
 [  2.32690232e-07   0.00000000e+00   0.00000000e+00]
 [  3.81315067e-01   0.00000000e+00   1.25439348e-01]]
>>> 

Instrucciones en Python

# Modulacion digital QPSK - pmf
# propuesta:edelros@espol.edu.ec
import numpy as np
import matplotlib.pyplot as plt

# INGRESO
# archivo = input('archivo de delta-sigma:' )
narchivo = 'elaguacate_deltasigma_datos.txt'
senal = np.loadtxt(narchivo,dtype=int)

# PROCEDIMIENTO
n = len(senal)

simbolos = [-1,0,1]
m = len(simbolos)

# Codificar de 2 en dos
agrupar = 2
cuenta  = np.zeros(shape=(m,m), dtype=int)
nmax = (n//agrupar)*agrupar
for i in range(0,nmax,agrupar):
    a = senal[i]
    b = senal[i+1]
    f = simbolos.index(a)
    c = simbolos.index(b)
    cuenta[f,c] = cuenta[f,c]+1

k = np.sum(cuenta)
pxy = cuenta/k

# SALIDA
print('datos cargados: ', n)
print('símbolos procesados: ', k)
print(cuenta)
print('pmf[x,y]')
print(pxy)


# Gráfica:
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

xpos, ypos = np.meshgrid(simbolos,simbolos)
xpos = xpos.flatten('F')

ypos = ypos.flatten('F')
zpos = np.zeros_like(xpos)
dx = 0.8 * np.ones_like(zpos)
dy = dx.copy()
dz = pxy.flatten()
ax.bar3d(xpos, ypos, zpos, dx, dy, dz, color='b', zsort='average')
plt.show()

Tarea: Obtener las pmf marginales del ejercicio.

pmf – Modulación BPSK

La modulación por desplazamiento de fase o PSK (Phase Shift Keying) es una forma de modulación angular en que se modifica la fase de la portadora acorde a valores discretos.

BPSK (PSK Binario)

La modulación consiste en el desplazamiento de fase para 2 símbolos.
También conocida como 2-PSK o PRK (Phase Reversal Keying).

Es la modulación más sencilla por  emplear solo 2 símbolos, con 1 bit de información cada uno.

Los símbolos suelen tener un valor de salto de fase de 0º para el 1 y 180º para el 0 (-1), como se muestra en un diagrama de constelación.

En cambio, su velocidad de transmisión es la más baja de las modulaciones de fase.

BPSK – pmf

La pmf de BPSK muestra el uso de cada símbolo durante una transmisión. Por ejemplo: de un ejercicio previo se codificó a Sigma-Delta una canción teniendo como resultado:

elaguacate_deltasigma_datos.txt

elaguacate_deltasigma_parametros.txt


resultado del algoritmo:

cantidad de símbolos:  8595119
cuenta de símbolos: [4297559       1 4297559]
pmf de símbolos:  [  4.99999942e-01   1.16345102e-07   4.99999942e-01]
>>> 

Instrucciones en Python

# PMF de una señal Sigma-Delta
# propuesta:edelros@espol.edu.ec
import numpy as np
import matplotlib.pyplot as plt

# INGRESO 
# archivo = input('archivo delta-sigma:' )
archivo = 'elaguacate_deltasigma_datos.txt'
senal = np.loadtxt(archivo, dtype=int)

# PROCEDIMIENTO
n = len(senal)
simbolos = [-1,0,1]
m = len(simbolos)
cuenta = np.zeros(m, dtype=int)
for i in range(0,n,1):
    bit = senal[i]
    cual = simbolos.index(bit)
    cuenta[cual] = cuenta[cual]+1
pmf = cuenta/n

# SALIDA
print('cantidad de símbolos: ', n)
print('cuenta de símbolos:', cuenta)
print('pmf de símbolos: ', pmf)

# Gráfica
plt.stem(simbolos,pmf)
plt.title('pmf sigma-delta')
plt.xlabel('símbolos')
plt.ylabel('frecuencia relativa')
plt.show()

Funciones de una Variable aleatoria

Sea X una variable aleatoria y sea g(x) una función de valor real definida en el eje real.

Defina Y= g(X), esto es. Y está determinada por la evaluación de la función en g(x) en el valor que ha tomado la variable aleatoria X.  Entonces Y también es una variable aleatoria.

Las probabilidades de los valores para Y dependen de la función g(x) así como la función distribución acumulada de X.

Considere una función no lineal Y=g(X) como la que se muestra en la figura.

donde |dy| es la longitud del intervalo y < Y ≤ (y+dy).
De forma similar, la probabilidad que el evento en cada intervalo es aproximadamente

f_Y(y)=\left.\sum_{k} \frac{f_X(x)}{|dy/dx|} \right|_{x=x_k} =\left.\sum_{k} f_X(x) \left| \frac{dx}{dy} \right| \right|_{x=x_k}

Ejemplo: León García 4.30 p.176

Sea X el valor de las muestras de voltaje de una señal de voz, y suponga que X tiene una distribución uniforme en el intervalo [-4d,4d].

Sea Y = q(X), donde la función característica de entrada-salida de un cuantizador (convertidor analógico-digital) se muetra en la figura. Encuentre la función de probabilidad de masa para Y.

Solución: El evento {Y=q} para q en SY es equivalente al evento {X en Iq}, donde Iq es un intervalo de puntos equivalentes mapeados en representación al punto q. La pmf de Y se encuentra evaluando:
P[Y=q] = \int_{I_q} f_X(t) dt

Lo que permite ver fácilmente que la representación de un punto tiene un intervalo de longitud d mappeado en él. Entonces existirán ocho posibles salidas equiprobables, es decir, P[Y=q] = 1/8 para q en SY

cdf – Modulación AM

Referencia: Leon W Couch 4-2 p234, «El Aguacate» introducción

Modulación en Amplitud (AM)

La modulación es el proceso de codificación de la información fuente, sonido o moduladora, dentro de una señal pasabanda s(t), resultande o modulada. La señal modulada se obtiene de:

senal(t) = A_c[1+moduladora(t)] cos(\omega_c t) s(t) = A_c[1+m(t)] cos(\omega_c t)

donde:

\omega_c = 2\pi f_c

fc es la frecuencia de la portadora o «carrier».
Ac es la amplitud de la portadora.

Como ejemplo, si se quiere enviar una señal de sonido obtenida de un archivo.wav modulada en Amplitud, la señal m(t) será:

muestra_GuitarraCuerda.wav

Instrucciones en Python

# pmf de un sonido
# entrada es archivo01
# propuesta:edelros@espol.edu.ec
import numpy as np
import matplotlib.pyplot as plt
import scipy.io.wavfile as waves
import scipy.stats as stats

# INGRESO 
# archivo01 = input('archivo de sonido 01: ' )
# k = int(input('muestras para ejemplo: '))
archivo01 = 'muestra_GuitarraCuerda.wav'
k = 500

# PROCEDIMIENTO
muestreo, sonido01 = waves.read(archivo01)

# Extrae un canal en caso de estéreo
canales = sonido01.shape
cuantos = len(canales)
canal = 0   
if (cuantos==1): # Monofónico
    uncanal = sonido01[:]  
if (cuantos>=2): # Estéreo
    uncanal = sonido01[:,canal]
    
moduladora = uncanal[0:k].astype(float)
dt = 1/muestreo
t  = np.arange(0,k*dt,dt)

# SALIDA GRAFICA
plt.plot(t,moduladora)
plt.title(' Moduladora m(t)')
plt.xlabel('t')
plt.ylabel('señal')
plt.plot()
plt.show()

Para el ejemplo, la señal de la portadora presentada tiene frecuencia de 5500 para que se pueda visualizar el efecto.
(Revisar frecuencias de portadoras AM estándares o ver el dial de un radio AM).

# Portadora:
fc = 5500
portadora = np.cos(2*np.pi*fc*t)

# SALIDA GRAFICA
plt.plot(t,portadora, color='orange')
plt.title(' Portadora')
plt.xlabel('t')
plt.ylabel('señal')
plt.plot()
plt.show()

Antes de aplicar la moduladora, se la normaliza para mantener la proporción en la gráfica

# normalizar y subir a positiva
moduladoranorm = moduladora/np.max(moduladora)
moduladora = (1+ moduladoranorm)

# Modular portadora
Ac = 1
modulada = Ac*moduladora*portadora

# SALIDA GRAFICA
plt.plot(t,moduladora,label='moduladora')
plt.plot(t,modulada,label='modulada')
plt.title(' Señal modulada S(t)')
plt.xlabel('t')
plt.ylabel('señal')
plt.legend()
plt.show()

cdf – una señal de sonido

Referencia: Leon W Couch apéndice B p675, «El Aguacate», pasillo introducción, Archivos de Audio.wav – Abrir, extraer una porción

De forma semejante al análisis para una señal triangular, se obtiene barriendo una ventana estrecha de Δx voltios de ancho, verticalmente a lo largo de las formas de onda y después midiendo la frecuencia relativa de la ocurrencia de voltajes en la ventana Δx.

El eje de tiempo se divide en n intervalos y la forma de onda aparece nΔx veces dentro de estos intervalos en la ventana Δx.

Se inicia abriendo el archivo 'muestra01_ElAguacateIntro.wav', seleccionando un canal en caso de ser estéreo. Para los cálculos se convierte a números reales ‘float’ de tipo estándar de python y para la gráfica se determina el rango de tiempo 't'.

# pmf de un sonido
# entrada es arcchivo01
# propuesta:edelros@espol.edu.ec
import numpy as np
import matplotlib.pyplot as plt
import scipy.io.wavfile as waves
import scipy.stats as stats

# INGRESO 
# archivo01 = input('archivo de sonido 01:' )
archivo01 = 'muestra01_ElAguacateIntro.wav'

# PROCEDIMIENTO
muestreo, sonido01 = waves.read(archivo01)

# Extrae un canal en caso de estéreo
canales=np.shape(sonido01)
cuantos=len(canales)
canal = 0   
if (cuantos==1): # Monofónico
    uncanal=sonido01[:]  
if (cuantos>=2): # Estéreo
    uncanal=sonido01[:,canal]
    
senal=uncanal.astype(float)
dt=1/muestreo
n=len(senal)
t=np.arange(0,n*dt,dt)

Se grafica la señal en observación de uncanal:

# SALIDA GRAFICA
plt.plot(t,senal)
plt.title(' Sonido')
plt.xlabel('t')
plt.ylabel('señal')
plt.plot()
plt.show()


Aplicando luego el mismo algoritmo usado para señales triangulares y senoidales, manteniendo la forma discreta.

# Función de Probabilidad de Masa, PMF
m=40  # intervalos eje vertical

#PROCEDIMIENTO
relativa = stats.relfreq(senal, numbins = m )
deltax=relativa.binsize

# Eje de frecuencias, por cada deltax
senalmin=np.min(senal)
senalmax=np.max(senal)
senalrango=np.linspace(senalmin,senalmax,m)

# SALIDA
print('frecuencia relativa:')
print(relativa.frequency)
print('Rango de Señal')
print(senalrango)
frecuencia relativa:
[ 0.00023583  0.00073469  0.00089796  0.00053515  0.00084354  0.00179592  0.00245805  0.00306576  0.0039093   0.00504308  0.0066576   0.0099229  0.01693424  0.02671202  0.03568254  0.05160998  0.06758277  0.07323356  0.08575057  0.09217234  0.11898413  0.08494331  0.07535601  0.06454422  0.05382313  0.03821315  0.02429932  0.01573696  0.01075737  0.00767347  0.00576871  0.00365533  0.00245805  0.00176871  0.00145125  0.00103401  0.0008254   0.00106122  0.00137868  0.0004898 ]
Rango de Señal
[-32768.         -31087.61538462 -29407.23076923 -27726.84615385 -26046.46153846 -24366.07692308 -22685.69230769 -21005.30769231 -19324.92307692 -17644.53846154 -15964.15384615 -14283.76923077 -12603.38461538 -10923.          -9242.61538462  -7562.23076923  -5881.84615385  -4201.46153846  -2521.07692308   -840.69230769    839.69230769   2520.07692308   4200.46153846   5880.84615385   7561.23076923   9241.61538462  10922.          12602.38461538  14282.76923077  15963.15384615  17643.53846154  19323.92307692  21004.30769231  22684.69230769  24365.07692308  26045.46153846  27725.84615385  29406.23076923  31086.61538462  32767.        ]
# SALIDA Grafico de PMF
plt.bar(senalrango,relativa.frequency, width=deltax*0.8)
plt.xlabel('Amplitud de señal')
plt.ylabel('PMF')
plt.show()

# Función distribución acumulada
acumulada=np.cumsum(relativa.frequency)

# SALIDA CDF
plt.step(senalrango,relativa.frequency,label='pmf', where='post')
plt.step(senalrango,acumulada,label='cdf', where='post')
plt.xlabel('Amplitud de señal')
plt.title(' Función de distribuión acumulada , CDF')
plt.legend()
plt.show()

Para grabar los archivos puede usar np.savetxt(‘nombrearchivo.txt’, arreglodata )

pdf – univariada Ejercicio

Referencia: Ross 2.33 p89

Ejercicio

Sea X una variable aleatoria con densidad de probabilidad:

f(x)= \begin{cases} c(1-x^2)&, -1<x<1 \\ 0 &, \text{en otro caso} \end{cases}

a) ¿Cuál es el valor de c? que permite hacer la función una pdf.

b) ¿Cuál es la función de distribución acumulada de X?

Solución

a)Solo es válido en el rango [-1,1], por lo que el integral es:

1 = \int_{-1}^{1} c(1-x^2) dx = c \int_{-1}^{1} (1-x^2) dx = c \int_{-1}^{1}dx - c \int_{-1}^{1}x^2 dx = c \left. x \right|_{-1}^{1} - c \left. \frac{x^3}{3} \right|_{-1}^{1} = c[1-(-1)] - c\frac{1^3-(-1^3)}{3} = 2c -\frac{2c}{3} 1 = \frac{4c}{3} c=\frac{3}{4}

Solución

b)La función es la integral hasta x:

F(y) = \frac{3}{4} \int_{-1}^{y} (1-x^2) dx = \frac{3}{4} \left. \left[ x - \frac{x^3}{3} \right] \right|_{-1}^{y} = = \frac{3}{4}\left[(y+1) - \left( \frac{y^3}{3} + \frac{1}{3} \right) \right] = F(y) = \frac{3}{4} \left[ y+\frac{2}{3} - \frac{y^3}{3} \right], 1<y<1

Instrucciones en Python

usando el resultado anterior:

import matplotlib.pyplot as plt
import numpy as np

def fxdensidad(X):
    n = len(X)
    Y = np.zeros(n,dtype=float)
    
    c = 3/4
    for i in range(0,n,1):
        x = X[i]
        if (x>=-1 and x<=1):
            y = c*(1-x**2)
            Y[i] = y
    return(Y)

# INGRESO
# rango [a,b] y muestras
a = -1
b = 1
m = 100

# PROCEDIMIENTO
deltax = (b-a)/m
x  = np.linspace(a,b,m)
fx = fxdensidad(x)

# Función de distribución acumulada
Fy = np.cumsum(fx)*deltax

# SALIDA Gráfico
plt.plot(x,fx,label='pdf')
plt.plot(x,Fy,label='cdf')
plt.xlabel('x')
plt.legend()
plt.show()

# Verificando resultado del integral vs la suma acumulada
def Fxacumulada(X):
    n = len(X)
    Y = np.zeros(n,dtype=float)
    c = 3/4
    for i in range(0,n,1):
        x=X[i]
        if (x>=-1 and x<=1):
            y=c*(x+ 2/3 -(x**3)/3)
            Y[i]=y
    return(Y)

# PROCEDIMIENTO
Fycalc = Fxacumulada(x)

# SALIDA Gráfico
plt.plot(x,fx,label='pdf')
plt.plot(x,Fy,label='cdf')
plt.plot(x,Fycalc,label='calculada')
plt.xlabel('x')
plt.legend()
plt.show()

cdf – Señal coseno(x)

Referencia: Ejemplo León-García 4.36 p180

Sea Y=cos(X), y supondremos que X es uniformemente distribuida en el intervalo de (0, 2π]. Y puede ser vista como una muestra de una señal sinusoidal a un instante aleatorio de tiempo que esta uniformemente distribuida en el periodo de la sinusoide.

Para encontrar la pdf, se tiene que la variable -1< y < 1

f_Y(y)=\left.\sum_{k} \frac{f_X(x)}{|dy/dx|} \right|_{x=x_k}

La función fX(x) es uniforme, por lo que el área del integral en el intervalo debe ser 1, es decir:

\int_{0}^{2\pi}c dx=1 =(2\pi-0)*c= 2\pi c = 1 c=\frac{1}{2\pi} f_X(x) = \frac{1}{2\pi}

De la figura se encuentra que la ecuación tiene dos puntos de intersección o dos soluciones:

x_0 = \cos ^{-1}(y) x_1 = 2\pi- x_0

por lo que se evalúa la derivada en cada punto de intersección:

\left.\frac{dy}{dx} \right|_{x_0}= -sin(x_0) = - sin(cos^{-1}(y)) \alpha = \cos^{-1}(x) \sin(\alpha) = y x^2 + y^2 =1 x = \sqrt{1-y^2} \left.\frac{dy}{dx} \right|_{x_0}= -\sqrt{1-y^2} \left.\frac{dy}{dx} \right|_{x_1}= -\sqrt{1-y^2}

dado que y0 = y1 = y

Aplicando la ecuación primera:

f_Y(y) = \frac{1}{2\pi \sqrt{1-y^2}} + \frac{1}{2\pi \sqrt{1-y^2}} = \frac{1}{\pi \sqrt{1-y^2}} -1 < y < 1

Gráfica del resultado

# pdf de una señal senoidal
import matplotlib.pyplot as plt
import numpy as np

# INGRESO
# n=int(input('numero de muestras: '))
n = 200

# PROCEDIMIENTO
t  = np.linspace(-1,1,n)
fy = np.zeros(n,dtype=float)
# Evaluar denominador no cero
for i in range(0,n,1):
    denominador = 1-t[i]**2
    if (denominador!=0):
        fy[i] = 1/(np.pi*np.sqrt(1-t[i]**2))
dt = t[1]-t[0]
Fy = np.cumsum(fy)*dt

# SALIDA
plt.plot(t,fy,label='pdf')
plt.plot(t,Fy,label='cdf')
plt.xlabel('x')
plt.legend()
plt.show()


Cálculo con un método numérico

Señal Coseno(x), pmf, cdf

Se obtiene barriendo una ventana horizontal estrecha de Δx voltios de ancho, verticalmente a lo largo de las formas de onda y después midiendo la frecuencia relativa de la ocurrencia de voltajes en la ventana Δx.

El eje de tiempo se divide en n intervalos y la forma de onda aparece nΔx veces dentro de estos intervalos en la ventana Δx.

Para observar lo indicado usando python, se presenta el siguiente grupo de instrucciones:

Genera la señal

En un intervalo [a,b] de tiempo, con n muestras en el intervalo y una señal coseno(x) con frecuencia fs Hz.

# Pmf de una senal periódica conocida
# definir la señal en la sección senal_t
import numpy as np
import scipy.signal as signal
import scipy.stats as stats
import matplotlib.pyplot as plt

def senal_t(t, fs):
    m = len(t)
    y = np.zeros(m, dtype=float)
    for i in range(0,m,1):
        y[i] = np.cos(2 * np.pi * fs * t[i])
    return(y)

# INGRESO
# Frecuencia de la señal en Hz
fs = 5
# Rango en tiempo de la señal y muestras
a = 0
b = 1
tramos = 2000

# PROCEDIMIENTO
muestreo = tramos+1
t = np.linspace(a, b, muestreo)
senal = senal_t(t, fs)

# SALIDA
plt.plot(t,senal)
plt.title(' Señal sen(x)')
plt.xlabel('t')
plt.ylabel('señal')
plt.show()

Determinar la función de probabilidad de masa PMF

Se divide el rango de valores posibles de la señal en m intervalos.

Para simplificar el conteo de valores por rango se usa la función scypy.stats.relfreq, que cuenta en m intervalos entre el rango de la señal, dando como resultado las frecuencias relativas a intervalos Δx.
\sum_{i=0}^{N} p_i(x)=1

Si se considera aproximar la función a contínua para observación, será necesario compensar el vector de relativas al dividir por Δx pues el conteo relativo depende del número de divisiones m.

# Pmf de una senal periódica conocida
# definir la señal en la sección senal_t
import numpy as np
import scipy.signal as signal
import scipy.stats as stats
import matplotlib.pyplot as plt

def senal_t(t, fs):
    m = len(t)
    y = np.zeros(m, dtype=float)
    for i in range(0,m,1):
        y[i] = np.cos(2 * np.pi * fs * t[i])
    return(y)

# INGRESO
# Frecuencia de la señal en Hz
fs = 5
# Rango en tiempo de la señal y muestras
a = 0
b = 1
tramos = 2000

# PROCEDIMIENTO
muestreo = tramos+1
t = np.linspace(a, b, muestreo)
senal = senal_t(t, fs)

# SALIDA
plt.plot(t,senal)
plt.title(' Señal sen(x)')
plt.xlabel('t')
plt.ylabel('señal')
plt.show()

# Función de Probabilidad de Masa, PMF
m = 50  # intervalos en análisis

#PROCEDIMIENTO
relativa = stats.relfreq(senal, numbins = m )
deltax = relativa.binsize
# considerando el deltax, para valor de PMF
relcontinua=relativa.frequency/deltax

# Eje de frecuencias, por cada deltax
senalmin = np.min(senal)
senalmax = np.max(senal)
senalrango = np.linspace(senalmin,senalmax,m)

# SALIDA
print('frecuencia relativa:')
print(relativa.frequency)
print('Rango de Señal')
print(senalrango)
print('Aproximación a contínua')
print(relcontinua)

# SALIDA Grafico de PMF
plt.subplot(211)
plt.bar(senalrango,relativa.frequency, width=deltax*0.8)
plt.xlabel('Amplitud de señal')
plt.ylabel('PMF')

plt.subplot(212)
plt.plot(senalrango,relcontinua)
plt.ylim(ymin=0,ymax=np.max(relcontinua))
plt.xlabel('Amplitud de señal')
plt.ylabel('Aproximación a PDF')
plt.show()

frecuencia relativa:
[ 0.045  0.034  0.023  0.018  0.017  0.014  0.014  0.012  0.012  0.011   0.011  0.01   0.01   0.01   0.009  0.009  0.009  0.008  0.008  0.009  0.008  0.007  0.008  0.008  0.007  0.008  0.007  0.007  0.007  0.007 
 ... 
0.008  0.007  0.008  0.008  0.008  0.008  0.008  0.009  0.009  0.009  0.009  0.009  0.01   0.01   0.011  0.011  0.012  0.013  0.013  0.015  0.016  0.019  0.023  0.033  0.046]
Rango de Señal
[-0.99999877 -0.97979676 -0.95959475 -0.93939274 -0.91919073 -0.89898873 -0.87878672 -0.85858471 -0.8383827  -0.8181807  -0.79797869 -0.77777668 -0.75757467 -0.73737266 -0.71717066 -0.69696865 -0.67676664 -0.65656463 
...
0.63636386  0.65656587  0.67676788  0.69696988  0.71717189  0.7373739   0.75757591  0.77777791  0.79797992  0.81818193  0.83838394  0.85858595  0.87878795  0.89898996  0.91919197  0.93939398  0.95959598  0.97979799  1.        ]
Aproximación a contínua
[ 2.22750138  1.68300104  1.1385007   0.89100055  0.84150052  0.69300043  0.69300043  0.59400037  0.59400037  0.54450034  0.54450034  0.49500031  0.49500031  0.49500031  0.44550028  0.44550028  0.44550028  0.39600024  
...
0.39600024  0.44550028  0.44550028  0.44550028  0.44550028  0.44550028  0.49500031  0.49500031  0.54450034  0.54450034  0.59400037  0.6435004   0.6435004   0.74250046  0.79200049  0.94050058  1.1385007   1.63350101  2.27700141]

Determinar la Función de distribucíón acumulada

Considere el caso discreto, solo es necesario ir acumulando los valores de «relativa».

Al usar la aproximación a contínua, la sumatoria debe considerar el área bajo la curva, por lo que los valores se multiplican por Δx antes de acumular los valores de las frecuencias.

# Función distribución acumulada
acumulada=np.cumsum(relcontinua*deltax)

# Salida CDF
# plt.step(senalrango,relcontinua,label='pdf', where='post')
plt.step(senalrango,acumulada,label='cdf', where='post')
plt.xlabel('Amplitud de señal')
plt.title(' Función de distribuión acumulada , CDF')
plt.legend()
plt.show()


Tarea: realice el ejercicio con otras señales periódicas.
Referencia: Leon W Couch apéndice B p675

cdf -Señal triangular

Referencia: Leon W Couch apéndice B p675

Señal Triangular, pmf, cdf

Se obtiene barriendo una ventana estrecha de Δx voltios de ancho, verticalmente a lo largo de las formas de onda y después midiendo la frecuencia relativa de la ocurrencia de voltajes en la ventana Δx.

El eje de tiempo se divide en n intervalos y la forma de onda aparece nΔx veces dentro de estos intervalos en la ventana Δx.

Para observar lo indicado usando python, se presenta el siguiente grupo de instrucciones:

Generar la señal

En un intervalo [a,b] de tiempo, con n muestras en el intervalo y una señal triangular con frecuencia fs Hz.

Las librerías de señales de scipy tiene la señal diente de sierra, con parámetro de simetría que permite variar la forma del triángulo para ajustarlo a una señal simétrica como la del ejemplo.

import matplotlib.pyplot as plt
import numpy as np
import scipy.signal as signal
import scipy.stats as stats

# INGRESO
# Rango en tiempo de la señal y muestras
a = 0
b = 1
n = 2000
# Frecuencia de la señal en Hz
fs = 5

# PROCEDIMIENTO
# simetria de la señal triangular diente de sierra
simetria = 0.5
t = np.linspace(a, b, n)
senal = signal.sawtooth(2 * np.pi * fs * t, simetria)

# SALIDA
plt.plot(t,senal)
plt.title('Señal Triangular')
plt.xlabel('t')
plt.ylabel('señal')
plt.show()

Determinar la función de probabilidad de masa PMF

Se divide el rango de valores posibles de la señal en m intervalos.

Para simplificar el conteo de valores por rango se usa la función scipy.stats.relfreq, que cuenta en m intervalos entre el rango de la señal, dando como resultado las frecuencias relativas a intervalos Δx

\sum_{i=0}^{N}p_i(x)=1

Si se considera aproximar la función a contínua para observación, será necesario compensar el vector de relativas al dividir por Δx pues el conteo relativo depende del número de divisiones m.

# Función de Probabilidad de Masa, PMF
m = 20  # intervalos en análisis

#PROCEDIMIENTO
relativa = stats.relfreq(senal, numbins = m )
deltax   = relativa.binsize

# considerando el deltax, para valor de PMF
relcontinua = relativa.frequency/deltax

# Eje de frecuencias, por cada deltax
senalmin = np.min(senal)
senalmax = np.max(senal)
senalrango = np.linspace(senalmin,senalmax,m)

# SALIDA
print('frecuencia relativa:')
print(relativa.frequency)
print('Rango de Señal')
print(senalrango)
print('Aproximación a contínua')
print(relcontinua)

# SALIDA Grafico de PMF
pa = 0-0.1 # rango eje frecuencias
pb = 1+0.1

plt.subplot(211)
plt.axis([senalmin-deltax,senalmax+deltax,pa,pb])
plt.bar(senalrango,relativa.frequency, width=deltax*0.8)
plt.xlabel('Amplitud de señal')
plt.ylabel('PMF')

plt.subplot(212)
plt.axis([senalmin-deltax,senalmax+deltax,pa,pb])
plt.plot(senalrango,relcontinua)
plt.xlabel('Amplitud de señal')
plt.ylabel('Aproximación a PDF')
plt.show()
frecuencia relativa:
[ 0.027  0.052  0.053  0.053  0.052  0.053  0.052  0.053  0.052  0.053  0.053  0.052  0.053  0.052  0.053  0.052  0.053  0.053  0.052  0.027]
Rango de Señal
[-1.        -0.8947895 -0.789579  -0.6843685 -0.579158  -0.4739475 -0.368737  -0.2635265 -0.158316  -0.0531055  0.052105   0.1573155  0.262526   0.3677365  0.472947   0.5781575  0.683368   0.7885785  0.893789   0.9989995]
Aproximación a contínua
[ 0.25662838  0.49424725  0.503752    0.503752    0.49424725  0.503752   0.49424725  0.503752    0.49424725  0.503752    0.503752    0.49424725  0.503752    0.49424725  0.503752    0.49424725  0.503752    0.503752  0.49424725  0.25662838]

Determinar la Función de distribucíón acumulada

Considere el caso discreto, solo es necesario ir acumulando los valores de «relativa».

Al usar la aproximación a contínua, la sumatoria debe considerar el área bajo la curva, por lo que los valores se multiplican por Δx antes de acumular los valores de las frecuencias.

# Función distribución acumulada
acumulada = np.cumsum(relcontinua*deltax)

# Salida CDF
plt.step(senalrango,relcontinua,label='pdf', where='post')
plt.step(senalrango,acumulada,label='cdf', where='post')
plt.xlabel('Amplitud de señal')
plt.title(' Función de distribuión acumulada , CDF')
plt.legend()
plt.show()


Tarea: realice el ejercicio con otras señales periódicas.

PMF – Teclado Qwerty

Referencia: Teclado Qwerty Wikipedia

Uso del teclado QWERTY

El nombre del teclado QWERTY proviene de las primeras seis letras de su fila superior, fue diseñado y patentado por Christopher Sholes en 1868 y vendido a Remington en 1873.

La distribución QWERTY se diseñó con objetivo de separar las letras más usadas de la zona central del teclado, para evitar que se atascaran las máquinas de escribir de primera generación. Actualmente, ésta propiedad no es más requerida, sin embargo se ha heredado la distribución en los teclados de computadora.

A partir de la frecuencia de uso de las letras del alfabeto, se requiere conocer la frecuencia de uso de cada fila del teclado. Los valores de frecuencia para cada letra se encuentran en el archivo: usoletras.txt que por cada línea registra la letra y frecuencia relativa separadas por una coma ‘,’.

archivo: usoletras.txt:
a, 0.11422682511 
b, 0.0118959769969 
c, 0.0464006717728 
d, 0.0543525280541 
...

Algoritmo en Python

# Analiza teclado QWERTY
# Datos desde Archivo 'usoletras.txt'
import numpy as np

# Ingreso
narchivo = input('Nombre del archivo:')
veces    = []
archivo  = open(narchivo,'r')
linea    = archivo.readline()
while not(linea == ''):
    partes = linea.split(',')
    letra  = partes[0]
    frecuencia = float(partes[1])
    veces.append([letra,frecuencia])
    linea = archivo.readline()
archivo.close()

# PROCEDIMIENTO
superior = 'qwertyuiop'
media    = 'asdfghjklñ'
inferior = 'zxcvbnm'
k = len(veces)
usofila = np.zeros(3,dtype=float)
for i in range(0,len(veces),1):
    if (veces[i][0] in superior):
        usofila[0] = usofila[0]+veces[i][1]
    if (veces[i][0] in media):
        usofila[1] = usofila[1]+veces[i][1]
    if (veces[i][0] in inferior):
        usofila[2] = usofila[2]+veces[i][1]

# SALIDA
print(usofila)

resultado:

[ 0.48999975  0.32815084  0.18184941]

La gráfica para pmf se obtiene al añadir las instrucciones:

# GRAFICA
% matplotlib inline
import matplotlib.pyplot as plt
plt.stem([0,1,2],usofila)
plt.title('PMF filas teclado QWERTY')
plt.xlabel('fila superior, media e inferior')
plt.show()

Tarea: En cada caso, realice la gráfica de funciones de probabilidad de masa (pmf) y la función de probabilidades acumulada (cdf)

  • Encuentre la frecuencia de uso de cada mano, presente la división propuesta de el teclado en dos partes: izquierda y derecha.
  • Realice el ejercicio para determinar la frecuencia de uso de cada dedo de cada mano. Presente un modelo gráfico de cada tecla, para mostrar de mejor forma la medida a obtener
  • con los resultados de éste ejercicio, considere llenar la siguiente tabla:
    mano izquierda mano derecha total fila
    superior
    media
    inferior
    total mano

PMF – Alfabeto

Referencia: Ross 2.2 p25, Telex, TTY o teletipo(Wikipedia)

Funciones de probabilidad de masa para alfabeto

Para el «TELEX», «TTY», «teletype» o sistema de transmisión/recepción de mensajes de texto mecanografiados, al desconocer el contenido del mensaje se podría considerar que cada letra presenta un comportamiento aleatorio. Se puede intuir que hay letras que son poco comunes como ‘x’ y otras muy comunes como ‘e’.

Para el modelo se requiere estimar función de probabilidad de masa (pmf), tomando como base solo el alfabeto incluyendo la letra ‘ñ’, sin discriminar mayúsculas y minúsculas.

Para un ensayo, se usaría un texto con una cantidad considerable de letras, como por ejemplo una obra literaria.

Por ejemplo: ‘elaguacate_Letra.txt

Referencia: https://achiras.net.ec/el-aguacate-un-pasillo-ecuatoriano-sin-tiempo/

Para procesar el texto se usa como entrada un archivo en formato .txt, analizando por línea, por símbolo y contando las veces que aparece cada letra del alfabeto. La frecuencia relativa de cada letra respecto al total de letras, permitirá visualizar la forma de la función probabilidad de masa (pmf) para el alfabeto.

Nota: Considere solo el total de letras, no el total de símbolos (no incluye «,;.!?» etc.)

Algoritmo en Python

# procesar un archivo de texto
# Determinar la función de probabilidad de masa
# para las letras del alfabeto(incluye ñ)
import numpy as np

# INGRESO
# archivo=input('archivo a leer.txt: ')
nombrearchivo='elaguacate_Letra.txt'

# PROCEDIMIENTO
alfabeto='abcdefghijklmnñopqrstuvwxyz'
k=len(alfabeto)
veces=np.zeros(k,dtype=int)
total=0
# procesa el archivo
archivo = open(nombrearchivo,'r')
unalinea = archivo.readline()
while not(unalinea==''):
    n=len(unalinea)
    unalinea = unalinea.strip('\n')
    unalinea = unalinea.lower()
    m=len(unalinea)
    for j in range(0,m,1):
        unsimbolo=unalinea[j]
        donde = alfabeto.find(unsimbolo)
        if (donde>=0): #Si no encuentra es negativo
            veces[donde]=veces[donde]+1
            total=total+1
    unalinea = archivo.readline()
archivo.close()

frelativa=veces/total
alfa=np.arange(0,len(alfabeto))

# SALIDA
print('Letras contadas: ', total)
print('i,letra,veces,frelativa')
for i in range(0,len(alfabeto),1):
    print(i, alfabeto[i],veces[i], frelativa[i])

el resultado obtenido es:

Letras contadas:  253
i,letra,veces,frelativa
0 a 25 0.098814229249
1 b 1 0.00395256916996
2 c 5 0.0197628458498
3 d 7 0.0276679841897
4 e 25 0.098814229249
5 f 4 0.0158102766798
6 g 0 0.0
7 h 2 0.00790513833992
8 i 22 0.0869565217391
9 j 1 0.00395256916996
10 k 0 0.0
11 l 15 0.0592885375494
12 m 15 0.0592885375494
13 n 20 0.0790513833992
14 ñ 0 0.0
15 o 24 0.0948616600791
16 p 4 0.0158102766798
17 q 3 0.0118577075099
18 r 16 0.0632411067194
19 s 21 0.0830039525692
20 t 16 0.0632411067194
21 u 16 0.0632411067194
22 v 3 0.0118577075099
23 w 0 0.0
24 x 0 0.0
25 y 7 0.0276679841897
26 z 1 0.00395256916996

para la gráfica se añade al algoritmo:

# GRAFICA
% matplotlib inline
import matplotlib.pyplot as plt
plt.stem(alfa,frelativa)
plt.title('PMF alfabeto')
plt.xlabel(alfabeto)
plt.show()


otro experimento realizado con:
Poe, Edgar Allan. Eureka. Vol. 13. EDAF, 2006.

tiene el siguiente resultado:

Letras contadas:  78598
i,letra,veces,frelativa
0 a 8978 0.11422682511
1 b 935 0.0118959769969
2 c 3647 0.0464006717728
3 d 4272 0.0543525280541
4 e 10455 0.133018651874
5 f 658 0.00837171429298
6 g 818 0.010407389501
7 h 632 0.00804091707168
8 i 5792 0.0736914425303
9 j 161 0.00204839817807
10 k 36 0.000458026921805
11 l 4203 0.0534746431207
12 m 2541 0.0323290668974
13 n 6126 0.0779409145271
14 ñ 46 0.000585256622306
15 o 6725 0.0855619735871
16 p 2271 0.0288938649838
17 q 692 0.00880429527469
18 r 4899 0.0623298302756
19 s 5988 0.0761851446602
20 t 3792 0.0482455024301
21 u 3362 0.0427746253085
22 v 647 0.00823176162243
23 w 34 0.000432580981704
24 x 177 0.00225196569887
25 y 491 0.00624697829461
26 z 220 0.00279905341103

Será necesario que realizar el experimento muchas veces para tener un comportamiento más general, se propone realizar al estudiante su experimento con otros textos.

Con los resultados, se requiere:

  1. Realizar la pmf para vocales
  2. Realizar la pmf para consonantes
  3. determine las letras con menor probabilidad de cada grupo
  4. escriba alguna recomendación para mejorar el experimento
  5. escriba al menos una conlusión

Considere lo siguiente:

Si en una transmisión de texto, por ruido en el canal se cambian aleatoriamente algunos caracteres,

  • ¿Cuáles cambios serían los que afectan menos al mensaje?
  • ¿Cuáles cambios serían los que afectan más al mensaje?

En caso de presentar el resultado de frecuencias relativas en un archivo:

# Archivo
narchivo='usoletras.txt'
archivo=open(narchivo,'w')
for i in range(0,k,1):
    linea=alfabeto[i]+','+str(frelativa[i])+'\n'
    archivo.write(linea)
archivo.close()