'create a mixture distribution
Parameters
mixing_dist : discrete frozen distribution
mixing distribution
base_dist : continuous distribution
parameterized distributions in the mixture
bd_args_func : callable
function that builds the tuple of args for the base_dist.
The function obtains as argument the values in the support of
the mixing distribution and should return an empty tuple or
a tuple of arrays.
bd_kwds_func : callable
function that builds the dictionary of kwds for the base_dist.
The function obtains as argument the values in the support of
the mixing distribution and should return an empty dictionary or
a dictionary with arrays as values.
cutoff : float
If the mixing distribution has infinite support, then the
distribution is truncated with approximately (subject to integer
conversion) the cutoff probability in the missing tail. Random
draws that are outside the truncated range are clipped, that is
assigned to the highest or lowest value in the truncated support.'

def __init__(self, mixing_dist, base_dist, bd_args_func, bd_kwds_func, cutoff=0.001):

    self.mixing_dist = mixing_dist
    self.base_dist = base_dist
    if (not np.isneginf(mixing_dist.dist.a)):
        lower = mixing_dist.dist.a
    else:
        lower = mixing_dist.ppf(0.0001)
    if (not np.isposinf(mixing_dist.dist.b)):
        upper = mixing_dist.dist.b
    else:
        upper = mixing_dist.isf(0.0001)
    self.ma = lower
    self.mb = upper
    mixing_support = np.arange(lower, (upper + 1))
    self.mixing_probs = mixing_dist.pmf(mixing_support)
    self.bd_args = bd_args_func(mixing_support)
    self.bd_kwds = bd_kwds_func(mixing_support)
