[edit] implementation of difference of two independent random variable as the correlation of the PDFs completed; summation pending due to unclear axis determination of the resultant PDF

This commit is contained in:
Sebastian Wehling-Benatelli 2016-02-15 20:13:02 +01:00
parent f2cad2e151
commit 3ee221b8eb

View File

@ -15,6 +15,9 @@ def create_axis(x0, incr, npts):
ax[i] = x0 + incr * i ax[i] = x0 + incr * i
return ax return ax
def find_nearest_index(array, value):
return (np.abs(array-value)).argmin()
def gauss_parameter(te, tm, tl, eta): def gauss_parameter(te, tm, tl, eta):
''' '''
@ -128,15 +131,16 @@ class ProbabilityDensityFunction(object):
assert isinstance(other, ProbabilityDensityFunction), \ assert isinstance(other, ProbabilityDensityFunction), \
'both operands must be of type ProbabilityDensityFunction' 'both operands must be of type ProbabilityDensityFunction'
x0, incr, npts, pdf_self, pdf_other = self.rearrange(other) raise NotImplementedError('implementation of resulting axis unclear - feature pending!')
# x0, incr, npts, pdf_self, pdf_other = self.rearrange(other)
pdf = np.convolve(pdf_self, pdf_other, 'same') * incr #
# pdf = np.convolve(pdf_self, pdf_other, 'same') * incr
# shift axis values for correct plotting #
midpoint = int(npts // 2) + 1 # # shift axis values for correct plotting
x0 += incr * midpoint # midpoint = npts / 2
# x0 = incr * midpoint
return ProbabilityDensityFunction(x0, incr, npts, pdf) #
# return ProbabilityDensityFunction(x0, incr, npts, pdf)
def __sub__(self, other): def __sub__(self, other):
assert isinstance(other, ProbabilityDensityFunction), \ assert isinstance(other, ProbabilityDensityFunction), \
@ -147,8 +151,8 @@ class ProbabilityDensityFunction(object):
pdf = np.correlate(pdf_self, pdf_other, 'same') * incr pdf = np.correlate(pdf_self, pdf_other, 'same') * incr
# shift axis values for correct plotting # shift axis values for correct plotting
midpoint = int(npts // 2) + 1 midpoint = npts / 2
x0 -= incr * midpoint x0 = -incr * midpoint
return ProbabilityDensityFunction(x0, incr, npts, pdf) return ProbabilityDensityFunction(x0, incr, npts, pdf)
@ -172,29 +176,49 @@ class ProbabilityDensityFunction(object):
self._x = np.array(x) self._x = np.array(x)
@classmethod @classmethod
def fromPick(self, incr, lbound, midpoint, rbound, decfact=0.01, type='gauss'): def fromPick(self, incr, lbound, barycentre, rbound, decfact=0.01, type='gauss'):
''' '''
Initialize a new ProbabilityDensityFunction object. Initialize a new ProbabilityDensityFunction object.
Takes incr, lbound, midpoint and rbound to derive x0 and the number Takes incr, lbound, barycentre and rbound to derive x0 and the number
of points npts for the axis vector. of points npts for the axis vector.
Maximum density Maximum density
is given at the midpoint and on the boundaries the function has is given at the barycentre and on the boundaries the function has
declined to decfact times the maximum value. Integration of the declined to decfact times the maximum value. Integration of the
function over a particular interval gives the probability for the function over a particular interval gives the probability for the
variable value to be in that interval. variable value to be in that interval.
''' '''
margin = 1.5 * np.max(midpoint - lbound, rbound - midpoint)
x0 = midpoint - margin # derive adequate window of definition
npts = int(2 * margin // incr) margin = 1.5 * np.max([barycentre - lbound, rbound - barycentre])
params = parameter[type](lbound, midpoint, rbound, decfact)
# find midpoint accounting also for `~obspy.UTCDateTime` object usage
try: try:
pdf = branches[type](create_axis(x0, incr, npts), midpoint, *params) midpoint = (rbound + lbound) / 2
except TypeError:
midpoint = (rbound + float(lbound)) / 2
# find x0 on a grid point and sufficient npts
n = int(np.ceil((barycentre - midpoint) / incr))
m = int(np.ceil((margin / incr)))
midpoint = barycentre - n * incr
margin = m * incr
x0 = midpoint - margin
npts = 2 * m
# calculate parameter for pdf representing function
params = parameter[type](lbound, barycentre, rbound, decfact)
# calculate pdf values
try:
pdf = branches[type](create_axis(x0, incr, npts), barycentre, *params)
except TypeError as e: except TypeError as e:
print('Warning:\n' + e.message + '\n' + 'trying timestamp instead') print('Warning:\n' + e.message + '\n' + 'trying timestamp instead')
assert isinstance(midpoint, UTCDateTime), 'object not capable of' \ assert isinstance(barycentre, UTCDateTime), 'object not capable of' \
' timestamp representation' ' timestamp representation'
pdf = branches[type](create_axis(x0, incr, npts), pdf = branches[type](create_axis(x0, incr, npts),
midpoint.timestamp, *params) barycentre.timestamp, *params)
# return the object
return ProbabilityDensityFunction(x0, incr, npts, pdf) return ProbabilityDensityFunction(x0, incr, npts, pdf)
def commonlimits(self, incr, other, max_npts=1e5): def commonlimits(self, incr, other, max_npts=1e5):
@ -209,37 +233,41 @@ class ProbabilityDensityFunction(object):
:param r2: :param r2:
:param max_npts: :param max_npts:
:return: :return:
''' '''
# >>> manu = ProbabilityDensityFunction.fromPick(0.01, 0.3, 0.5, 0.54)
# >>> auto = ProbabilityDensityFunction.fromPick(0.01, 0.3, 0.34, 0.54)
# >>> manu.commonlimits(0.01, auto)
# (
l1 = self.x0 l1 = self.x0
r1 = np.max(self.axis) r1 = l1 + self.incr * self.npts
l2 = other.x0 l2 = other.x0
r2 = np.max(other.axis) r2 = l2 + other.incr * other.npts
if l1 >= l2 and r1 >= r2: if l1 < l2:
x0 = l2
npts = int(r1 - x0 // incr)
elif l1 < l2 and r1 >= r2:
x0 = l1 x0 = l1
npts = int(r1 - x0 // incr)
elif l1 >= l2 and r1 < r2:
x0 = l2
npts = int(r2 - x0 // incr)
elif l1 >= r2:
x0 = l2
npts = int(r1 - x0 // incr)
elif l2 >= r1:
x0 = l1
npts = int(r2 - x0 // incr)
else: else:
x0 = None x0 = l2
npts = None
# calculate index for rounding
ri = int(np.ceil(np.abs(np.log10(incr))))
if r1 < r2:
npts = int(round(r2 - x0, ri) // incr)
else:
npts = int(round(r1 - x0, ri) // incr)
if npts > max_npts: if npts > max_npts:
raise ValueError('Maximum number of points exceeded:\n' raise ValueError('Maximum number of points exceeded:\n'
'max_npts - %d\n' 'max_npts - %d\n'
'npts - %d\n' % (max_npts, npts)) 'npts - %d\n' % (max_npts, npts))
npts = np.max([npts, self.npts, other.npts])
if npts < self.npts or npts < other.npts:
raise ValueError('new npts is to small')
return x0, npts return x0, npts
@ -268,9 +296,9 @@ class ProbabilityDensityFunction(object):
x = create_axis(x0, incr, npts) x = create_axis(x0, incr, npts)
sstart = np.where(x == self.x0) sstart = find_nearest_index(x, self.x0)
s_end = sstart + self.data.size s_end = sstart + self.data.size
ostart = np.where(x == other.x0) ostart = find_nearest_index(x, other.x0)
o_end = ostart + other.data.size o_end = ostart + other.data.size
pdf_self[sstart:s_end] = self.data pdf_self[sstart:s_end] = self.data