[ot-users] Custom distribution in FORM

regis lebrun regis_anne.lebrun_dutfoy at yahoo.fr
Fri Nov 10 20:11:57 CET 2017


You can easily implement this distribution using OpenTURNS unique feature regarding distribution algebra (see https://en.wikipedia.org/wiki/Johnson%27s_SU-distribution):

import openturns as ot
lamb = 1.5
xi = 1.1
delta = 2.0
gamma = 1.0
distJU = ((ot.Normal() - gamma) / delta).sinh() * lamb + xi
print("distJU=", distJU)

You will get:
distJU= RandomMixture(1.1 + 1.5 * CompositeDistribution=f(RandomMixture(Normal(mu = -0.5, sigma = 0.5))) with f=[x]->[sinh(x)])

and a graph similar to the one given on the wikipedia page.

Your script contains some bugs (computeQuantile, getMean, getStandardDeviation should return the result as a float sequence of size 1) and a missing method, namely getRange(). To get a running distribution you must implement getRange() and computeCDF(), all the other methods have a generic implementation, but these generic algorithms may be slow or inaccurate in difficult situations, so the more methods you provide the most efficient your distribution is.

The online documentation (http://openturns.github.io/openturns/master/user_manual/_generated/openturns.PythonDistribution.html?highlight=pythondistribution) is very poor and will be updated. You can have a look at https://github.com/openturns/openturns/blob/master/python/test/t_Distribution_python.py for an example of a custom Python distribution.

You could also have used the SciPyDistribution wrapper of scipy distributions (see http://openturns.github.io/openturns/master/user_manual/_generated/openturns.SciPyDistribution.html and https://github.com/openturns/openturns/blob/master/python/test/t_Distribution_scipy.py):

import openturns as ot
import scipy.stats as st

lamb = 1.5
xi = 1.1
delta = 2.0
gamma = 1.0
distJU = ot.Distribution(ot.ScyPyDistribution(st.johnsonsu(gamma, delta, loc=xi, scale=lamb)))

but unfortunately this wrapper has a bug for unbounded distributions, resulting in a wrong range and a boggus computeQuantile() method.

Thanks for the question, it raised a lot of problems in OT!

Best regards,


Le vendredi 10 novembre 2017 à 18:42:19 UTC+1, Phil Fernandes <phil.fernandes at enbridge.com> a écrit : 



I am attempting to use a custom continuous probability distribution for a probability of failure calculation via FORM, but when I try to create a ComposedDistribution with my custom dist, the program fails with

NotImplementedError: Wrong number or type of arguments for overloaded function 'new_ComposedDistribution'.


The custom dist is defined as


class JohnsonSU(ot.PythonDistribution):

    def __init__(self, gamma=1, xi=0, delta=0.5, lam=1):

        super(JohnsonSU, self).__init__(1)

        if np.any(delta <= 0):

            raise ValueError('Delta must be >0.')

        if np.any(lam <= 0):

            raise ValueError('Lambda must be >0.')


        self.gamma = gamma  # shape 1

        self.xi = xi    # location

        self.delta = delta  # shape 2, >0

        self.lam = lam  # scale, >0

        self.scipy_dist = st.johnsonsu(self.gamma, self.delta, loc=self.xi, scale=self.lam)


    def computeCDF(self, x):

        return self.scipy_dist.cdf(x)


    def computePDF(self, x):

        return self.scipy_dist.pdf(x)


    def computeQuantile(self, p):

        return self.scipy_dist.ppf(p)


    def getMean(self):

        return self.scipy_dist.mean()


    def getStandardDeviation(self):

        return self.scipy_dist.std()



Are there additional functions that must be defined in order for the PythonDistribution to be compatible with existing OpenTurns Distributions? Or, is there a straightforward way that I could add arbitrary distributions to the OpenTurns source code? 


Many thanks!


Phil Fernandes   P.Eng, MASc
Engineer, Reliability Assessment


TEL: 780-420-8210  |  FAX: 780-420-5234   
7045 Enbridge Centre, 10175 101 Street NW, Edmonton, AB, T5J 0H3

Integrity. Safety. Respect.


OpenTURNS users mailing list
users at openturns.org

More information about the users mailing list