text: #!/usr/bin/python3
  #Paquetes
  import numpy as np
  from numpy.random import randint
  from PIL import Image
  from bitstring import BitArray
  import matplotlib.pyplot as plt
  
  class modulation():
  
  	'''
  	Esta es una clase que contiene los
  	metodos necesarios para implementar
  	un modulador PAM, con medio ideal y
  	ruidoso, asi como un demodulador. 
  	Debe usarse junto a las clases
  	source() y sys_com() de las sim-
  	mulacuones anteriores para ensamblar
  	el sistema de comunicaciones completo
  	'''
  	
      #El constructor:
  	def __init__(self, m, k, n):
  		
  		#numero de paquetes 1 x k:
  		self.m = m
  		
  		#dimension de cada paquete de bits:
  		self.k = k 
  		
  		#dimension de paquetes 1 x n:
  		self.n = n # n > k 
  		
  	#================METODOS==================  
  
  	'''
  	Se crea una funcion que le asigna simbolos a 
  	cada secuencia de bits que sale del canal bcT
  	se sabe que M=2^k siendo k=16. M=65536. Aqui
  	k es n, es la salida del codificador de canal
  	'''
  	def symbol_modulator(self, bcT):
  		x, y = bcT.shape
  		'''
  		se pasa el vector de bits obtenido en el 
  		canal a senal codigo se pasan de bits a
  		números del 0 a 2^16.
  		'''
  		an = []
  		for i in range(x):
  			 decimal = BitArray(bcT[i])
  			 an.append(decimal.uint)   
  
  		return an
  	#==========================================
  
  	''' 
  	Funcion para simular la senal PAM que va ser 
  	transmitida por el medio. Para simplificacion, 
  	solo se toman los primeros 15 simbolos de an 
  	y se repiten 30 veces cada una para que se 
  	vea bien la grafica
  	'''
  	def PAM(self,an):
  		dt = 0.1
  		t = np.arange(0, 45, dt)  
  		p = []
  		for i in range(15):
  		    an[i] 
  		    for j in range(30):
  		        p.append(an[i])
  		plt.plot(t,p)
  		plt.xlabel('Tiempo [s]')
  		plt.ylabel('Amplitud')
  		plt.title('Señal modulada PAM')
  		plt.show()
  
  	#===========================================
  	'''
  	Un metodo que simula un medio de 
  	transmision ruidoso. Pide por 
  	parametro an, que corresponde a 
  	la secuencia de simbolos y N, 
  	el porcentaje de ruido deseado 
  	entre [0 - 100]
  	'''
  	def noised_transmitter(self, an, N):
  		#cantidad de ruido
  		noise = round(len(an) * (N / 100))
  
  		#simbolos aleatorios
  		a = randint(0, 2**16, size = (noise, 1))
  		symbs = a.transpose()[0]
  
  		#indices aleatorios
  		b = randint(0, self.m, size = (noise, 1))
  		index = b.transpose()[0]
  
  		#insertando errores en an:
  		k = 0
  		for i in index:
  			an[i] = symbs[k]
  			k += 1
  		
  		return an
  
  	#=============================================
  	def symbol_demodulator(self, an):
  		x = []; bits_sec = []
  		#pasa de decimal a binario con 16 bits:
  		for i in range(len(an)):                	
  			x.append(bin(an[i])[2:].zfill(16))
  
  		#Se pasan a vectores tipo enteros:
  		for i in range(len(x)):						  
  			bits_sec.append([int(i) for i in x[i]])
  		'''
  		se ordena en una matriz de tal forma 
  		que de igual a bcT:
  		'''
  		yn = np.reshape(bits_sec,(len(x), 16)) 		
  
  		return yn
  	#==============================================
  
  
  
  