1 // SWIG file Distribution.i
2
3 %{
4 #include "openturns/Distribution.hxx"
5 #include "openturns/PythonDistribution.hxx"
6 %}
7
8 %include Distribution_doc.i
9
10 %include UncertaintyModelCopulaCollection.i
11
12 OTTypedInterfaceObjectHelper(Distribution)
13 OTTypedCollectionInterfaceObjectHelper(Distribution)
14
15 %ignore OT::Distribution::pow;
16 %ignore OT::Distribution::setWeight;
17 %ignore OT::Distribution::getWeight;
18
19 %include openturns/Distribution.hxx
20
21 namespace OT {
22
23 %extend Distribution {
24
Distribution(const Distribution & other)25 Distribution(const Distribution & other)
26 {
27 return new OT::Distribution(other);
28 }
29
Distribution(PyObject * pyObj)30 Distribution(PyObject * pyObj)
31 {
32 return new OT::Distribution( new OT::PythonDistribution( pyObj ) );
33 }
34
__add__(Scalar s)35 Distribution __add__ (Scalar s)
36 {
37 return *self + s;
38 }
39
__radd__(Scalar s)40 Distribution __radd__ (Scalar s)
41 {
42 return *self + s;
43 }
44
__sub__(Scalar s)45 Distribution __sub__(Scalar s)
46 {
47 return *self - s;
48 }
49
__rsub__(Scalar s)50 Distribution __rsub__(Scalar s)
51 {
52 return (*self * (-1.0)) + s;
53 }
54
__mul__(Scalar s)55 Distribution __mul__(Scalar s)
56 {
57 return (*self) * s;
58 }
59
__rmul__(Scalar s)60 Distribution __rmul__(Scalar s)
61 {
62 return (*self) * s;
63 }
64
__div__(Scalar s)65 Distribution __div__(Scalar s)
66 {
67 return (*self) / s;
68 }
69
__pow__(const Scalar s)70 Distribution __pow__(const Scalar s) { return self->pow(s); }
71
__rdiv__(Scalar s)72 Distribution __rdiv__(Scalar s) { return self->inverse() * s; }
73
__rtruediv__(Scalar s)74 Distribution __rtruediv__(Scalar s) { return self->inverse() * s; }
75
76 #if SWIG_VERSION < 0x030011
__truediv__(Scalar s)77 Distribution __truediv__(Scalar s) { return (*self) / s; }
78 #endif
79
80 } // class Distribution
81 } // namespace OT
82
83 %pythoncode %{
84 from openturns.typ import Interval
85
86 class PythonDistribution(object):
87 """
88 Allow to override Distribution from Python.
89
90 Parameters
91 ----------
92 dim : positive int
93 the distribution dimension
94
95 Examples
96 --------
97 Not useful on its own, see the examples section on how to inherit from it.
98 """
99 def __init__(self, dim=0):
100 """
101 Constructor.
102 """
103 self.__dim = dim
104
105 def __str__(self):
106 return 'PythonDistribution -> #%d' % self.__dim
107
108 def __repr__(self):
109 return self.__str__()
110
111 def getDimension(self):
112 """
113 Dimension accessor.
114 """
115 return self.__dim
116
117 def computeCDF(self, X):
118 """
119 CDF accessor.
120 """
121 raise RuntimeError('You must define a method computeCDF(x) -> cdf, where cdf is a float')
122
123
124 class SciPyDistribution(PythonDistribution):
125 """
126 Allow to override Distribution from a scipy distribution.
127
128 Parameters
129 ----------
130 dist : a scipy.stats distribution
131 The distribution to wrap
132
133 Examples
134 --------
135 >>> import openturns as ot
136 >>> import scipy.stats as st # doctest: +SKIP
137 >>> scipy_dist = st.johnsonsu(2.55, 2.25) # doctest: +SKIP
138 >>> distribution = ot.Distribution(ot.SciPyDistribution(scipy_dist)) # doctest: +SKIP
139 >>> distribution.getRealization() # doctest: +SKIP
140 """
141 def __init__(self, dist):
142 super(SciPyDistribution, self).__init__(1)
143 if dist.__class__.__name__ != 'rv_frozen':
144 raise TypeError('Argument is not a scipy distribution')
145 self._dist = dist
146
147 # compute range
148 from openturns import ResourceMap
149 cdf_epsilon = ResourceMap.GetAsScalar('Distribution-DefaultCDFEpsilon')
150 lb = dist.ppf(0.0)
151 ub = dist.ppf(1.0)
152 flb = lb != float('-inf')
153 fub = ub != float('+inf')
154 if not flb:
155 lb = dist.ppf(cdf_epsilon)
156 if not fub:
157 ub = dist.ppf(1.0 - cdf_epsilon)
158 self.__range = Interval([lb], [ub])
159 self.__range.setFiniteLowerBound([int(flb)])
160 self.__range.setFiniteUpperBound([int(fub)])
161
162 def getRange(self):
163 return self.__range
164
165 def getRealization(self):
166 rvs = self._dist.rvs()
167 return [rvs]
168
169 def getSample(self, size):
170 rvs = self._dist.rvs(size)
171 return rvs.reshape(size, 1)
172
173 def computePDF(self, X):
174 pdf = self._dist.pdf(X[0])
175 return pdf
176
177 def computeCDF(self, X):
178 cdf = self._dist.cdf(X[0])
179 return cdf
180
181 def getMean(self):
182 mean = float(self._dist.stats('m'))
183 return [mean]
184
185 def getStandardDeviation(self):
186 var = float(self._dist.stats('v'))
187 std = var ** 0.5
188 return [std]
189
190 def getSkewness(self):
191 skewness = float(self._dist.stats('s'))
192 return [skewness]
193
194 def getKurtosis(self):
195 kurtosis = float(self._dist.stats('k')) + 3.0
196 return [kurtosis]
197
198 def getMoment(self, n):
199 moment = self._dist.moment(n)
200 return [moment]
201
202 def computeScalarQuantile(self, p, tail=False):
203 q = self._dist.ppf(1.0 - p if tail else p)
204 return q
205
206 def computeQuantile(self, prob, tail=False):
207 p = 1.0 - prob if tail else prob
208 q = self._dist.ppf(p)
209 return [q]
210
211 def getParameter(self):
212 return self._dist.args
213
214 def setParameter(self, params):
215 size = len(self._dist.args)
216 if len(params) != size:
217 raise ValueError('Parameter must be of size %d' % size)
218 self._dist.args = params
219
220 def getParameterDescription(self):
221 size = len(self._dist.args)
222 return ['parameter' + str(i + 1) for i in range(size)]
223
224
225 class ChaospyDistribution(PythonDistribution):
226 """
227 Allow to override Distribution from a chaospy distribution.
228
229 Parameters
230 ----------
231 dist : a chaospy distribution
232 The distribution to wrap. It is currently limited to stochastically
233 independent distributions as chaopy distributions doesn't implement CDF
234 computation for dependencies.
235
236 Examples
237 --------
238 >>> import openturns as ot
239 >>> import chaospy as cp # doctest: +SKIP
240 >>> chaospy_dist = cp.J(cp.Triangular(1.0, 2.0, 3.0), cp.F(4.0, 5.0)) # doctest: +SKIP
241 >>> distribution = ot.Distribution(ot.ChaospyDistribution(chaospy_dist)) # doctest: +SKIP
242 >>> distribution.getRealization() # doctest: +SKIP
243 """
244 def __init__(self, dist):
245 super(ChaospyDistribution, self).__init__(len(dist))
246 from chaospy import Iid, J, __version__
247 independent = len(dist) == 1
248 independent |= isinstance(dist, Iid)
249 if __version__ < '4.0.0':
250 from chaospy import get_dependencies
251 independent |= isinstance(dist, J) and not get_dependencies(*dist)
252 else:
253 independent |= not dist.stochastic_dependent
254 if not independent:
255 raise Exception(
256 "Dependent chaospy distributions doesn't implement CDF computation")
257 self._dist = dist
258 self.__range = Interval(dist.lower, dist.upper)
259
260 def getRange(self):
261 return self.__range
262
263 def getRealization(self):
264 rvs = self._dist.sample(1).flatten()
265 return rvs
266
267 def getSample(self, size):
268 rvs = self._dist.sample(size).T
269 return rvs.reshape(size, len(self._dist))
270
271 def computePDF(self, X):
272 pdf = self._dist.pdf(X)
273 return pdf
274
275 def computeCDF(self, X):
276 cdf = self._dist.cdf(X)
277 return cdf
278
279 def getMean(self):
280 import chaospy as cp
281 mean = cp.E(self._dist).reshape([len(self._dist)])
282 return mean
283
284 def getStandardDeviation(self):
285 import chaospy as cp
286 std = cp.Std(self._dist).reshape([len(self._dist)])
287 return std
288
289 def getSkewness(self):
290 import chaospy as cp
291 skewness = cp.Skew(self._dist).reshape([len(self._dist)])
292 return skewness
293
294 def getKurtosis(self):
295 import chaospy as cp
296 kurtosis = cp.Kurt(self._dist).reshape([len(self._dist)]) + 3.0
297 return kurtosis
298
299 def getMoment(self, n):
300 moment = self._dist.mom([n] * len(self._dist))
301 return moment
302
303 def computeScalarQuantile(self, p, tail=False):
304 if len(self._dist) > 1:
305 raise Exception(
306 "Multivariate distribution doesn't implement scalar quantile")
307 q = self._dist.inv(1 - p if tail else p)
308 return float(q)
309
310 def computeQuantile(self, prob, tail=False):
311 p = 1.0 - prob if tail else prob
312 q = self._dist.inv(p).flatten()
313 return q
314 %}
315