How to create a Rician random variable?

瘦欲@ 提交于 2019-12-12 07:22:22

问题


I'm trying to model a signal detection problem using Sympy, and need two random variables. One with a Rayleigh distribution to model noise, and one with a Rician distribution to model signal+noise. Sympy provides a Rayleigh distribution, but not a Rician-- or at least not one by that name.

What's the best way of creating one? Does it exist under a different name? Is there a way to manipulate existing distributions into a Rician?


Following advice from @asmeurer, I've implemented my own Rice distribution, like so:

from sympy.stats.crv_types import rv
from sympy.stats.crv import SingleContinuousDistribution

class RicianDistribution(SingleContinuousDistribution):
    _argnames=('nu','sigma')
    @property
    def set(self): return Interval(0,oo)

    def pdf(self,x):
        nu,sigma=self.nu, self.sigma
        return (x/sigma**2)*exp(-(x**2+nu**2)/(2*sigma**2))*besseli(0,x*nu/sigma**2)

def Rician(name,nu,sigma):
    return rv(name,RicianDistribution,(nu,sigma))

The distribution seems to match both Wikipedia and Scipy, but oddly I'm getting different results than Scipy. I'll ask that question separately (asked and answered).

As a side note, the following line makes it possible to lambdify the density function, which includes a Bessel function:

printing.lambdarepr.LambdaPrinter._print_besseli=(lambda self,expr: 'i0(%s)'%expr.argument)

It's not generalized to all Bessel functions, but works for the zero order modified Bessel of the first kind used in the Rician distribution.


回答1:


If you know the pdf function, it's easy to create a new distribution with sympy.stats. Take a look at the existing distributions in the sympy source. You just need to subclass SingleContinuousDistribution and define some methods. For example, here is the normal distribution (with the docstrings removed):

class NormalDistribution(SingleContinuousDistribution):
    _argnames = ('mean', 'std')

    @staticmethod
    def check(mean, std):
        _value_check(std > 0, "Standard deviation must be positive")

    def pdf(self, x):
        return exp(-(x - self.mean)**2 / (2*self.std**2)) / (sqrt(2*pi)*self.std)

    def sample(self):
        return random.normalvariate(self.mean, self.std)


def Normal(name, mean, std):
    return rv(name, NormalDistribution, (mean, std))



回答2:


Yes, you can generate the Rice from chi-squared and Poisson. See any thorough Rice discussion, such as https://en.wikipedia.org/wiki/Rice_distribution:

Another case where Rice(nu,sigma) comes from the following steps:

  1. Generate P having a Poisson distribution with parameter (also mean, for a Poisson) lambda = nu^2 / (2*sigma^2).
  2. Generate X having a chi-squared distribution with 2P + 2 degrees of freedom.
  3. Set R = sigma * sqrt(X).


来源:https://stackoverflow.com/questions/32981363/how-to-create-a-rician-random-variable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!