1313
1414
1515class ContinuousDistribution (abc .ABC ):
16- """Continuous probabiliy distribution function
16+ """Continuous probabiliy distribution function.
1717
1818 Partially implements the interface of scipy.stats.rv_continuous, but all
1919 methods should be applicable along an axis so fields can be processed in
2020 a grid point-wise fashion.
2121 """
2222
23- @abc .abstracmethod
2423 @classmethod
24+ @abc .abstractmethod
2525 def fit (cls , sample , axis ):
26- """Determine distribution parameters from a sample of data"""
26+ """Determine distribution parameters from a sample of data. """
2727
2828 @abc .abstractmethod
2929 def cdf (self , x ):
30- """Evaluate the continuous distribution function"""
30+ """Evaluate the continuous distribution function. """
3131
3232 @abc .abstractmethod
3333 def ppf (self , x ):
34- """Evaluate the inverse CDF (percent point function)"""
34+ """Evaluate the inverse CDF (percent point function). """
3535
3636
3737# Temporary drop-in replacement for scipy.stats.lmoment from scipy v0.15
3838def _lmoment (sample , order = (1 , 2 ), axis = 0 ):
39- """Compute first 2 L-moments of dataset along first axis"""
39+ """Compute first 2 L-moments of dataset along first axis. """
4040 if len (order ) != 2 or order [0 ] != 1 or order [1 ] != 2 :
4141 raise NotImplementedError
4242 if axis != 0 :
@@ -87,8 +87,12 @@ def _lmoment(sample, order=(1, 2), axis=0):
8787 return np .stack ([sums [0 ], sums [1 ]])
8888
8989
90+ def _expand_dims_after (arr , ndim ):
91+ return np .expand_dims (arr , axis = list (range (- ndim , 0 )))
92+
93+
9094class MaxGumbel (ContinuousDistribution ):
91- """Gumbel distribution for extreme values
95+ """Gumbel distribution for extreme values.
9296
9397 Parameters
9498 ----------
@@ -98,14 +102,12 @@ class MaxGumbel(ContinuousDistribution):
98102 Scale parameter.
99103 """
100104
101- def __init__ (self , mu , sigma ): # TODO: needs an axis argument?
102- self .mu = np .asarray (mu )
103- self .sigma = np .asarray (sigma )
104- assert self .mu .shape == self .sigma .shape
105+ def __init__ (self , mu , sigma ):
106+ self .mu , self .sigma = np .broadcast_arrays (mu , sigma )
105107
106108 @classmethod
107109 def fit (cls , sample , axis = 0 ):
108- """Gumbel distribution with parameters fitted to sample values
110+ """Gumbel distribution with parameters fitted to sample values.
109111
110112 Parameters
111113 ----------
@@ -124,8 +126,18 @@ def fit(cls, sample, axis=0):
124126 mu = lmom [0 ] - sigma * 0.5772
125127 return cls (mu , sigma )
126128
129+ @property
130+ def shape (self ):
131+ """Tuple of dimensions."""
132+ return self .mu .shape
133+
134+ @property
135+ def ndim (self ):
136+ """Number of dimensions."""
137+ return self .mu .ndim
138+
127139 def cdf (self , x ):
128- """Evaluate the cumulative distribution function
140+ """Evaluate the cumulative distribution function.
129141
130142 Parameters
131143 ----------
@@ -137,10 +149,11 @@ def cdf(self, x):
137149 The probability that a random variable X from the distribution is less
138150 than or equal to the input x.
139151 """
140- return 1.0 - np .exp (- np .exp ((self .mu - x ) / self .sigma )) # TODO vectorize along axis properly
152+ x = _expand_dims_after (x , self .ndim )
153+ return 1.0 - np .exp (- np .exp ((self .mu - x ) / self .sigma ))
141154
142155 def ppf (self , p ):
143- """Evaluate the inverse cumulative distribution function
156+ """Evaluate the inverse cumulative distribution function.
144157
145158 Parameters
146159 ----------
@@ -152,4 +165,5 @@ def ppf(self, p):
152165 x such that the probability of a random variable from the distribution
153166 taking a value less than or equal to x is p.
154167 """
155- return self .mu - self .sigma * np .log (- np .log (1.0 - p )) # TODO vectorize along axis properly
168+ p = _expand_dims_after (p , self .ndim )
169+ return self .mu - self .sigma * np .log (- np .log (1.0 - p ))
0 commit comments