Python实现rician莱斯衰落和rician莱斯信道

基本概念

Example

来自Github-Rician-Fading-Python

2.1 Rician衰落类

# -*- coding: utf-8 -*-
"""
Created on Wed Nov  4 18:55:46 2020

@author: Jonathan Browning
"""

import numpy as np
from scipy.stats import gaussian_kde as kdf
from scipy import special as sp

class Rice:
    # numSamples = 2*(10**6)  # the number of samples used in the simulation
    # numSamples = 64 #表示要产生的随机数的长度
    r = np.linspace(0, 6, 6000) # theoretical envelope PDF x axes
    theta = np.linspace(-np.pi, np.pi, 6000)    # theoretical phase PDF x axes
    
    def __init__(self, K, r_hat_2, phi,numSamples):
        
        # # user input checks and assigns value
        self.K = self.input_Check(K, "K", 0, 50)
        self.r_hat_2 = self.input_Check(r_hat_2, "\hat{r}^2", 0.5, 2.5)  
        self.phi = self.input_Check(phi, "\phi", -np.pi, np.pi)
        self.numSamples = numSamples
        # user input checks and assigns value
        
        # simulating and theri densities 
        self.multipathFading = self.complex_Multipath_Fading()
        self.xdataEnv, self.ydataEnv = self.envelope_Density()
        self.xdataPh, self.ydataPh = self.phase_Density()
        
        # theoretical PDFs calculated
        self.envelopeProbability = self.envelope_PDF()
        self.phaseProbability = self.phase_PDF()

    def input_Check(self, data, inputName, lower, upper):
        # input_Check checks the user inputs
        
        # has a value been entered
        if data == "":
            raise ValueError(" ".join((inputName, "must have a numeric value")))
        
        # incase of an non-numeric input 
        try:
            data = float(data)
        except:    
            raise ValueError(" ".join((inputName, "must have a numeric value")))
    
        # data must be within the range
        if data < lower or data > upper:
            raise ValueError(" ".join((inputName, f"must be in the range [{lower:.2f}, {upper:.2f}]")))
        
        return data

    def calculate_Means(self):
        # calculate_means calculates the means of the complex Gaussians representing the
        # in-phase and quadrature components
        
        p = np.sqrt(self.K * self.r_hat_2 / (1+self.K)) * np.cos(self.phi)
        q = np.sqrt(self.K * self.r_hat_2 / (1+self.K)) * np.sin(self.phi)
        
        return p, q
    
    def scattered_Component(self):
        # scattered_Component calculates the power of the scattered signal component
        
        sigma = np.sqrt(self.r_hat_2 / ( 2 * (1+self.K) ) )
        
        return sigma
    
    def generate_Gaussians(self, mean, sigma):
        # generate_Gaussians generates the Gaussian random variables
        
        gaussians = np.random.default_rng().normal(mean, sigma, self.numSamples)
        
        return gaussians
    
    def complex_Multipath_Fading(self):
        # complex_Multipath_Fading generates the complex fading random variables
        
        p, q = self.calculate_Means()
        sigma = self.scattered_Component()
        multipathFading = self.generate_Gaussians(p, sigma) + (1j*self.generate_Gaussians(q, sigma))
        
        return multipathFading
    
    def envelope_PDF(self):
        # envelope_PDF calculates the theoretical envelope PDF
        
        PDF = 2 * (1+self.K) * self.r / self.r_hat_2 \
            * np.exp(- self.K - ((1+self.K)*self.r**2)/self.r_hat_2) \
            * np.i0(2 * self.r * np.sqrt(self.K*(1+self.K)/self.r_hat_2))
            
        return PDF

    def phase_PDF(self):
        # phase_PDF calculates the theoretical phase PDF
        
        def q_func(x):
        # Q-function
        
            return 0.5-0.5*sp.erf(x/np.sqrt(2))     
        
        PDF = (1/(2*np.pi))* np.exp(- self.K) * (1 + (np.sqrt(4*np.pi*self.K) \
              * np.exp(self.K * (np.cos(self.theta-self.phi))**2) *np.cos(self.theta-self.phi)) \
              * (1 - q_func(np.sqrt(2*self.K) * np.cos(self.theta-self.phi))))
        
        return PDF
        
    
    def envelope_Density(self):
        # envelope_Density finds the envelope PDF of the simulated random variables
        
        R = np.sqrt((np.real(self.multipathFading))**2 + (np.imag(self.multipathFading))**2)
        kde = kdf(R)
        x = np.linspace(R.min(), R.max(), 100)
        p = kde(x)
        
        return x, p
    
    def phase_Density(self):
        # phase_Density finds the phase PDF of the simulated random variables
        
        R = np.angle(self.multipathFading)
        kde = kdf(R)
        x = np.linspace(R.min(), R.max(), 100)
        p = kde(x)
        
        return x, p
  

写一个Demo测试程序

from rice import *
K =1 # K因子
hat = 1 # 振幅
phi = 1 # 相位
numSamples = 16	# 随机样本的长度
s = Rice(1,1,1,16)
# rician衰落随机数
print(s.multipathFading)

2.2 Ricican信道

# signal输入的信号
# channelResponse rician衰落随机数,就是以上代码求的s.multipathFading
# SNRdb,信噪比
def rician_channel(signal, channelResponse, SNRdb):
	# 卷积
    convolved = np.convolve(signal, channelResponse)
    signal_power = np.mean(abs(convolved**2))
    sigma2 = signal_power * 10**(-SNRdb / 10)
    # 噪声
    noise = np.sqrt(sigma2 / 2) * (np.random.randn(*convolved.shape) + 1j * np.random.randn(*convolved.shape))
    return convolved + noise
 
上一篇:Java on Visual Studio Code的更新 – 2021年3月


下一篇:李宏毅机器学习课程笔记-4.3分类模型之逻辑回归