pep8 + updated wafo.stats packages

master
Per.Andreas.Brodtkorb 10 years ago
parent 629ed411c9
commit d308357c5b

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>google_pywafo</name>
<name>pywafo</name>
<comment></comment>
<projects>
</projects>
@ -10,6 +10,16 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>auto,full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/wafo_stats_tests.launch</value>
</dictionary>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.python.pydev.pythonNature</nature>

@ -3,8 +3,8 @@
<pydev_project>
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
<path>/google_pywafo/src</path>
<path>/pywafo/src</path>
</pydev_pathproperty>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
</pydev_project>

@ -1,4 +1,4 @@
Metadata-Version: 1.0
Metadata-Version: 1.1
Name: wafo
Version: 0.1.2
Summary: Statistical analysis and simulation of random waves and random loads

@ -4,17 +4,19 @@ gendocwafo.py
manifest
setup.py
setup_old.py
test_all.py
src/epydoc_wafo.prj
src/Wafo.egg-info/PKG-INFO
src/Wafo.egg-info/SOURCES.txt
src/Wafo.egg-info/dependency_links.txt
src/Wafo.egg-info/top_level.txt
src/wafo/MSO.py
src/wafo/MSPPT.py
src/wafo/SpecData1D.mm
src/wafo/__init__.py
src/wafo/bitwise.py
src/wafo/c_library.pyd
src/wafo/c_library.so
src/wafo/containers.py
src/wafo/cov2mod.pyd
src/wafo/dctpack.py
src/wafo/definitions.py
@ -28,6 +30,7 @@ src/wafo/info.py
src/wafo/integrate.py
src/wafo/interpolate.py
src/wafo/kdetools.py
src/wafo/magic.py
src/wafo/meshgrid.py
src/wafo/misc.py
src/wafo/mvn.pyd
@ -39,20 +42,26 @@ src/wafo/objects.py
src/wafo/plotbackend.py
src/wafo/polynomial.py
src/wafo/polynomial_old.py
src/wafo/pychip.py
src/wafo/powerpoint.py
src/wafo/resize_problem.py
src/wafo/rindmod.pyd
src/wafo/rindmod.so
src/wafo/sg_filter.py
src/wafo/version.py
src/wafo/wafodata.py
src/wafo/wtraits.py
src/wafo/wtraits2.py
src/wafo/wtraits3.py
src/wafo.egg-info/SOURCES.txt
src/wafo/covariance/__init__.py
src/wafo/covariance/core.py
src/wafo/data/__init__.py
src/wafo/data/__init__.pyc
src/wafo/data/atlantic.dat
src/wafo/data/gfaks89.dat
src/wafo/data/gfaksr89.dat
src/wafo/data/info.py
src/wafo/data/info.pyc
src/wafo/data/info.~py
src/wafo/data/japansea.dat
src/wafo/data/northsea.dat
@ -276,30 +285,47 @@ src/wafo/source/test_f90/types.f90
src/wafo/source/test_f90/types.mod
src/wafo/spectrum/__init__.py
src/wafo/spectrum/core.py
src/wafo/spectrum/dispersion_relation.py
src/wafo/spectrum/models.py
src/wafo/spectrum/test/test_dispersion_relation.py
src/wafo/spectrum/test/test_models.py
src/wafo/spectrum/test/test_models.pyc
src/wafo/spectrum/test/test_specdata1d.py
src/wafo/spectrum/test/test_specdata1d.pyc
src/wafo/stats/__init__.py
src/wafo/stats/core.py
src/wafo/stats/distributions.py
src/wafo/stats/distributions_juli2010.py
src/wafo/stats/estimation.py
src/wafo/stats/kde_test.py
src/wafo/stats/misc.py
src/wafo/stats/six.py
src/wafo/stats/sklearn_test.py
src/wafo/stats/twolumps.py
src/wafo/stats/tests/test_distributions.py
src/wafo/stats/tests/test_estimation.py
src/wafo/test/__init__.py
src/wafo/test/__init__.pyc
src/wafo/test/test_gaussian.py
src/wafo/test/test_gaussian.pyc
src/wafo/test/test_kdetools.py
src/wafo/test/test_kdetools.pyc
src/wafo/test/test_misc.py
src/wafo/test/test_misc.pyc
src/wafo/test/test_objects.py
src/wafo/test/test_objects.pyc
src/wafo/transform/__init__.py
src/wafo/transform/core.py
src/wafo/transform/models.py
src/wafo/transform/models.~py
src/wafo/transform/test/__init__.py
src/wafo/transform/test/__init__.pyc
src/wafo/transform/test/test_models.py
src/wafo/transform/test/test_models.pyc
src/wafo/transform/test/test_trdata.py
src/wafo/transform/test/test_trdata.pyc
src/wafo/wave_theory/__init__.py
src/wafo/wave_theory/core.py
src/wafo/wave_theory/dispersion_relation.py
src/wafo/wave_theory/test/__init__.py
src/wafo/wave_theory/test/__init__.pyc
src/wafo/wave_theory/test/test_dispersion_relation.py
src/wafo/wave_theory/test/test_dispersion_relation.pyc

@ -1,26 +1,27 @@
from __future__ import division, print_function, absolute_import
from info import __doc__
import misc
import data
import demos
import kdetools
import objects
import spectrum
import transform
import definitions
import polynomial
import stats
import interpolate
import dctpack
from .info import __doc__
from . import misc
from . import data
from . import demos
from . import kdetools
from . import objects
from . import spectrum
from . import transform
from . import definitions
from . import polynomial
from . import stats
from . import interpolate
from . import dctpack
try:
import fig
from . import fig
except ImportError:
print 'fig import only supported on Windows'
print('fig import only supported on Windows')
try:
from wafo.version import version as __version__
except ImportError:
__version__='nobuilt'
__version__ = 'nobuilt'
from numpy.testing import Tester
test = Tester().test

@ -2,13 +2,13 @@
Module extending the bitoperator capabilites of numpy
'''
from numpy import (bitwise_and, bitwise_or, #@UnresolvedImport
bitwise_not, binary_repr, #@UnresolvedImport @UnusedImport
bitwise_xor, where, arange) #@UnresolvedImport @UnusedImport
#import numpy as np
from numpy import (bitwise_and, bitwise_or,
bitwise_not, binary_repr, # @UnusedImport
bitwise_xor, where, arange) # @UnusedImport
__all__ = ['bitwise_and', 'bitwise_or', 'bitwise_not', 'binary_repr',
'bitwise_xor', 'getbit', 'setbit', 'getbits', 'setbits']
def getbit(i, bit):
"""
Get bit at specified position
@ -32,12 +32,14 @@ def getbit(i, bit):
"""
return bitwise_and(i, 1 << bit) >> bit
def getbits(i, numbits=8):
"""
Returns bits of i in a list
"""
return getbit(i, arange(0, numbits))
def setbit(i, bit, value=1):
"""
Set bit at specified position
@ -60,9 +62,10 @@ def setbit(i, bit, value=1):
"""
val1 = 1 << bit
val0 = bitwise_not(val1)
return where((value==0) & (i==i) & (bit==bit), bitwise_and(i, val0),
return where((value == 0) & (i == i) & (bit == bit), bitwise_and(i, val0),
bitwise_or(i, val1))
def setbits(bitlist):
"""
Set bits of val to values in bitlist
@ -81,9 +84,12 @@ def setbits(bitlist):
val |= j << i
return val
def test_docstrings():
import doctest
doctest.testmod()
print('Testing docstrings in %s' % __file__)
doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
if __name__ == '__main__':
test_docstrings()

@ -1,34 +1,42 @@
import warnings
from graphutil import cltext
from graphutil import cltext # @UnresolvedImport
from plotbackend import plotbackend
from time import gmtime, strftime
import numpy as np
from scipy.integrate.quadrature import cumtrapz #@UnresolvedImport
from scipy.integrate.quadrature import cumtrapz # @UnresolvedImport
from scipy import interpolate
from scipy import integrate
__all__ = ['PlotData', 'AxisLabels']
def empty_copy(obj):
class Empty(obj.__class__):
def __init__(self):
pass
newcopy = Empty()
newcopy.__class__ = obj.__class__
return newcopy
def _set_seed(iseed):
if iseed != None:
if iseed is not None:
try:
np.random.set_state(iseed)
except:
np.random.seed(iseed)
def now():
'''
Return current date and time as a string
'''
return strftime("%a, %d %b %Y %H:%M:%S", gmtime())
class PlotData(object):
'''
Container class for data with interpolation and plotting methods
@ -66,6 +74,7 @@ class PlotData(object):
>>> h = d3.plot()
'''
def __init__(self, data=None, args=None, *args2, **kwds):
self.data = data
self.args = args
@ -118,7 +127,8 @@ class PlotData(object):
>>> x = np.arange(-2, 2, 0.4)
>>> xi = np.arange(-2, 2, 0.1)
>>> d = PlotData(np.sin(x), x, xlab='x', ylab='sin', title='sinus', plot_args=['r.'])
>>> d = PlotData(np.sin(x), x, xlab='x', ylab='sin', title='sinus',
... plot_args=['r.'])
>>> di = PlotData(d.eval_points(xi), xi)
>>> hi = di.plot()
>>> h = d.plot()
@ -132,7 +142,8 @@ class PlotData(object):
if isinstance(self.args, (list, tuple)): # Multidimensional data
ndim = len(self.args)
if ndim < 2:
msg = '''Unable to determine plotter-type, because len(self.args)<2.
msg = '''
Unable to determine plotter-type, because len(self.args)<2.
If the data is 1D, then self.args should be a vector!
If the data is 2D, then length(self.args) should be 2.
If the data is 3D, then length(self.args) should be 3.
@ -140,9 +151,11 @@ class PlotData(object):
warnings.warn(msg)
else:
xi = np.meshgrid(*self.args)
return interpolate.griddata(xi, self.data.ravel(), points, **options)
else: #One dimensional data
return interpolate.griddata(self.args, self.data, points, **options)
return interpolate.griddata(
xi, self.data.ravel(), points, **options)
else: # One dimensional data
return interpolate.griddata(
self.args, self.data, points, **options)
def integrate(self, a, b, **kwds):
'''
@ -153,13 +166,14 @@ class PlotData(object):
array([ 0.99940055, 0.85543644, 1.04553343])
'''
method = kwds.pop('method','trapz')
method = kwds.pop('method', 'trapz')
fun = getattr(integrate, method)
if isinstance(self.args, (list, tuple)): # Multidimensional data
raise NotImplementedError('integration for ndim>1 not implemented')
#ndim = len(self.args)
#if ndim < 2:
# msg = '''Unable to determine plotter-type, because len(self.args)<2.
# if ndim < 2:
# msg = '''Unable to determine plotter-type, because
# len(self.args)<2.
# If the data is 1D, then self.args should be a vector!
# If the data is 2D, then length(self.args) should be 2.
# If the data is 3D, then length(self.args) should be 3.
@ -167,34 +181,41 @@ class PlotData(object):
# warnings.warn(msg)
# else:
# return interpolate.griddata(self.args, self.data.ravel(), **kwds)
else: #One dimensional data
else: # One dimensional data
return_ci = kwds.pop('return_ci', False)
x = self.args
ix = np.flatnonzero((a<x) & (x<b) )
ix = np.flatnonzero((a < x) & (x < b))
xi = np.hstack((a, x.take(ix), b))
fi = np.hstack((self.eval_points(a),self.data.take(ix),self.eval_points(b)))
fi = np.hstack(
(self.eval_points(a),
self.data.take(ix),
self.eval_points(b)))
res = fun(fi, xi, **kwds)
if return_ci:
return np.hstack((res, fun(self.dataCI[ix,:].T, xi[1:-1], **kwds)))
return np.hstack(
(res, fun(self.dataCI[ix, :].T, xi[1:-1], **kwds)))
return res
def plot(self, *args, **kwds):
axis = kwds.pop('axis',None)
axis = kwds.pop('axis', None)
if axis is None:
axis = plotbackend.gca()
tmp = None
default_plotflag = self.plot_kwds.get('plotflag',None)
default_plotflag = self.plot_kwds.get('plotflag', None)
plotflag = kwds.get('plotflag', default_plotflag)
if not plotflag and self.children != None:
if not plotflag and self.children is not None:
axis.hold('on')
tmp = []
child_args = kwds.pop('plot_args_children', tuple(self.plot_args_children))
child_args = kwds.pop(
'plot_args_children',
tuple(
self.plot_args_children))
child_kwds = dict(self.plot_kwds_children).copy()
child_kwds.update(kwds.pop('plot_kwds_children', {}))
child_kwds['axis'] = axis
for child in self.children:
tmp1 = child(*child_args, **child_kwds)
if tmp1 != None:
if tmp1 is not None:
tmp.append(tmp1)
if len(tmp) == 0:
tmp = None
@ -207,12 +228,14 @@ class PlotData(object):
def setplotter(self, plotmethod=None):
'''
Set plotter based on the data type data_1d, data_2d, data_3d or data_nd
Set plotter based on the data type:
data_1d, data_2d, data_3d or data_nd
'''
if isinstance(self.args, (list, tuple)): # Multidimensional data
ndim = len(self.args)
if ndim < 2:
msg = '''Unable to determine plotter-type, because len(self.args)<2.
msg = '''
Unable to determine plotter-type, because len(self.args)<2.
If the data is 1D, then self.args should be a vector!
If the data is 2D, then length(self.args) should be 2.
If the data is 3D, then length(self.args) should be 3.
@ -223,25 +246,31 @@ class PlotData(object):
else:
warnings.warn('Plotter method not implemented for ndim>2')
else: #One dimensional data
else: # One dimensional data
self.plotter = Plotter_1d(plotmethod)
def show(self):
self.plotter.show()
def show(self, *args, **kwds):
self.plotter.show(*args, **kwds)
__call__ = plot
interpolate = eval_points
class AxisLabels:
def __init__(self, title='', xlab='', ylab='', zlab='', **kwds):
self.title = title
self.xlab = xlab
self.ylab = ylab
self.zlab = zlab
def __repr__(self):
return self.__str__()
def __str__(self):
return '%s\n%s\n%s\n%s\n' % (self.title, self.xlab, self.ylab, self.zlab)
return '%s\n%s\n%s\n%s\n' % (
self.title, self.xlab, self.ylab, self.zlab)
def copy(self):
newcopy = empty_copy(self)
newcopy.__dict__.update(self.__dict__)
@ -252,18 +281,22 @@ class AxisLabels:
axis = plotbackend.gca()
try:
h = []
for fun, txt in zip(('set_title', 'set_xlabel','set_ylabel', 'set_ylabel'),
(self.title,self.xlab,self.ylab, self.zlab)):
for fun, txt in zip(
('set_title', 'set_xlabel', 'set_ylabel', 'set_ylabel'),
(self.title, self.xlab, self.ylab, self.zlab)):
if txt:
if fun.startswith('set_title'):
title0 = axis.get_title()
txt = title0 +'\n' + txt
if title0.lower().strip() != txt.lower().strip():
txt = title0 + '\n' + txt
h.append(getattr(axis, fun)(txt))
return h
except:
pass
class Plotter_1d(object):
"""
Parameters
@ -280,6 +313,7 @@ class Plotter_1d(object):
step : stair-step plot
scatter : scatter plot
"""
def __init__(self, plotmethod='plot'):
self.plotfun = None
if plotmethod is None:
@ -291,11 +325,11 @@ class Plotter_1d(object):
# except:
# pass
def show(self):
plotbackend.show()
def show(self, *args, **kwds):
plotbackend.show(*args, **kwds)
def plot(self, wdata, *args, **kwds):
axis = kwds.pop('axis',None)
axis = kwds.pop('axis', None)
if axis is None:
axis = plotbackend.gca()
plotflag = kwds.pop('plotflag', False)
@ -323,6 +357,7 @@ class Plotter_1d(object):
return h1
__call__ = plot
def plot1d(axis, args, data, dataCI, plotflag, *varargin, **kwds):
plottype = np.mod(plotflag, 10)
@ -335,18 +370,32 @@ def plot1d(axis, args, data, dataCI, plotflag, *varargin, **kwds):
elif plottype == 3:
H = axis.stem(args, data, *varargin, **kwds)
elif plottype == 4:
H = axis.errorbar(args, data, yerr=[dataCI[:,0] - data, dataCI[:,1] - data], *varargin, **kwds)
H = axis.errorbar(
args,
data,
yerr=[
dataCI[
:,
0] - data,
dataCI[
:,
1] - data],
*varargin,
**kwds)
elif plottype == 5:
H = axis.bar(args, data, *varargin, **kwds)
elif plottype == 6:
level = 0
if np.isfinite(level):
H = axis.fill_between(args, data, level, *varargin, **kwds);
H = axis.fill_between(args, data, level, *varargin, **kwds)
else:
H = axis.fill_between(args, data, *varargin, **kwds);
elif plottype==7:
H = axis.fill_between(args, data, *varargin, **kwds)
elif plottype == 7:
H = axis.plot(args, data, *varargin, **kwds)
H = axis.fill_between(args, dataCI[:,0], dataCI[:,1], alpha=0.2, color='r');
H = axis.fill_between(
args, dataCI[
:, 0], dataCI[
:, 1], alpha=0.2, color='r')
scale = plotscale(plotflag)
logXscale = 'x' in scale
@ -369,16 +418,17 @@ def plot1d(axis, args, data, dataCI, plotflag, *varargin, **kwds):
ax[3] = 11 * np.log10(fmax1)
ax[2] = ax[3] - 40
else:
ax[3] = 1.15 * fmax1;
ax[2] = ax[3] * 1e-4;
ax[3] = 1.15 * fmax1
ax[2] = ax[3] * 1e-4
axis.axis(ax)
if np.any(dataCI) and plottype < 3:
axis.hold(True)
plot1d(axis, args, dataCI, (), plotflag, 'r--');
plot1d(axis, args, dataCI, (), plotflag, 'r--')
return H
def plotscale(plotflag):
'''
Return plotscale from plotflag
@ -419,10 +469,19 @@ def plotscale(plotflag):
logZscaleId = (np.mod(scaleId // 100, 10) > 0) * 4
scaleId = logYscaleId + logXscaleId + logZscaleId
scales = ['linear', 'xlog', 'ylog', 'xylog', 'zlog', 'xzlog', 'yzlog', 'xyzlog']
scales = [
'linear',
'xlog',
'ylog',
'xylog',
'zlog',
'xzlog',
'yzlog',
'xyzlog']
return scales[scaleId]
def transformdata(x, f, plotflag):
transFlag = np.mod(plotflag // 10, 10)
if transFlag == 0:
@ -438,11 +497,14 @@ def transformdata(x, f, plotflag):
data = -np.log1p(-cumtrapz(f, x))
else:
if any(f < 0):
raise ValueError('Invalid plotflag: Data or dataCI is negative, but must be positive')
raise ValueError('Invalid plotflag: Data or dataCI is ' +
'negative, but must be positive')
data = 10 * np.log10(f)
return data
class Plotter_2d(Plotter_1d):
"""
Parameters
----------
@ -463,6 +525,7 @@ class Plotter_2d(Plotter_1d):
h1 = plot2d(axis, wdata, plotflag, *args, **kwds)
return h1
def plot2d(axis, wdata, plotflag, *args, **kwds):
f = wdata
if isinstance(wdata.args, (list, tuple)):
@ -471,7 +534,8 @@ def plot2d(axis, wdata, plotflag, *args, **kwds):
args1 = tuple((wdata.args,)) + (wdata.data,) + args
if plotflag in (1, 6, 7, 8, 9):
isPL = False
if hasattr(f, 'clevels') and len(f.clevels) > 0: # check if contour levels is submitted
# check if contour levels is submitted
if hasattr(f, 'clevels') and len(f.clevels) > 0:
CL = f.clevels
isPL = hasattr(f, 'plevels') and f.plevels is not None
if isPL:
@ -479,22 +543,26 @@ def plot2d(axis, wdata, plotflag, *args, **kwds):
else:
dmax = np.max(f.data)
dmin = np.min(f.data)
CL = dmax - (dmax - dmin) * (1 - np.r_[0.01, 0.025, 0.05, 0.1, 0.2, 0.4, 0.5, 0.75])
CL = dmax - (dmax - dmin) * \
(1 - np.r_[0.01, 0.025, 0.05, 0.1, 0.2, 0.4, 0.5, 0.75])
clvec = np.sort(CL)
if plotflag in [1, 8, 9]:
h = axis.contour(*args1, levels=CL, **kwds);
#else:
h = axis.contour(*args1, levels=CL, **kwds)
# else:
# [cs hcs] = contour3(f.x{:},f.f,CL,sym);
if plotflag in (1, 6):
ncl = len(clvec)
if ncl > 12:
ncl = 12
warnings.warn('Only the first 12 levels will be listed in table.')
warnings.warn(
'Only the first 12 levels will be listed in table.')
clvals = PL[:ncl] if isPL else clvec[:ncl]
unused_axcl = cltext(clvals, percent=isPL) # print contour level text
unused_axcl = cltext(
clvals,
percent=isPL) # print contour level text
elif any(plotflag == [7, 9]):
axis.clabel(h)
else:
@ -502,41 +570,47 @@ def plot2d(axis, wdata, plotflag, *args, **kwds):
elif plotflag == 2:
h = axis.mesh(*args1, **kwds)
elif plotflag == 3:
h = axis.surf(*args1, **kwds) #shading interp % flat, faceted % surfc
# shading interp % flat, faceted % surfc
h = axis.surf(*args1, **kwds)
elif plotflag == 4:
h = axis.waterfall(*args1, **kwds)
elif plotflag == 5:
h = axis.pcolor(*args1, **kwds) #%shading interp % flat, faceted
h = axis.pcolor(*args1, **kwds) # %shading interp % flat, faceted
elif plotflag == 10:
h = axis.contourf(*args1, **kwds)
axis.clabel(h)
plotbackend.colorbar(h)
else:
raise ValueError('unknown option for plotflag')
#if any(plotflag==(2:5))
# if any(plotflag==(2:5))
# shading(shad);
#end
# end
# pass
def test_plotdata():
plotbackend.ioff()
x = np.arange(-2, 2, 0.4)
xi = np.arange(-2, 2, 0.1)
d = PlotData(np.sin(x), x, xlab='x', ylab='sin', title='sinus', plot_args=['r.'])
d = PlotData(np.sin(x), x, xlab='x', ylab='sin', title='sinus',
plot_args=['r.'])
di = PlotData(d.eval_points(xi, method='cubic'), xi)
unused_hi = di.plot()
unused_h = d.plot()
d.show()
def test_docstrings():
import doctest
doctest.testmod()
print('Testing docstrings in %s' % __file__)
doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
def main():
pass
if __name__ == '__main__':
test_docstrings()
#test_plotdata()
#main()
# test_plotdata()
# main()

@ -2,6 +2,6 @@
Covariance package in WAFO Toolbox.
"""
from core import * #CovData1D
from core import * # CovData1D
#import models
#import dispersion_relation
import estimation

@ -16,25 +16,28 @@ date : Date and time of creation or change.
from __future__ import division
import warnings
#import numpy as np
from numpy import (zeros, sqrt, dot, inf, where, pi, nan, #@UnresolvedImport
atleast_1d, hstack, vstack, r_, linspace, flatnonzero, size, #@UnresolvedImport
isnan, finfo, diag, ceil, floor, random, pi) #@UnresolvedImport
from numpy.fft import fft #as fft
import numpy as np
from numpy import (zeros, ones, sqrt, inf, where, nan,
atleast_1d, hstack, r_, linspace, flatnonzero, size,
isnan, finfo, diag, ceil, floor, random, pi)
from numpy.fft import fft
from numpy.random import randn
import scipy.interpolate as interpolate
from scipy.linalg import toeplitz, sqrtm, svd, cholesky, diagsvd, pinv
from scipy.linalg import toeplitz, lstsq
from scipy import sparse
from pylab import stineman_interp
from wafo.wafodata import PlotData
from wafo.misc import sub_dict_select, nextpow2 #, JITImport
from wafo.containers import PlotData
from wafo.misc import sub_dict_select, nextpow2 # , JITImport
import wafo.spectrum as _wafospec
from scipy.sparse.linalg.dsolve.linsolve import spsolve
from scipy.sparse.base import issparse
from scipy.signal.windows import parzen
#_wafospec = JITImport('wafo.spectrum')
__all__ = ['CovData1D']
def _set_seed(iseed):
if iseed != None:
try:
@ -43,67 +46,48 @@ def _set_seed(iseed):
random.seed(iseed)
#def rndnormnd(cov, mean=0.0, cases=1, method='svd'):
# '''
# Random vectors from a multivariate Normal distribution
#
# Parameters
# ----------
# mean, cov : array-like
# mean and covariance, respectively.
# cases : scalar integer
# number of sample vectors
# method : string
# defining squareroot method for covariance
# 'svd' : Singular value decomp. (stable, quite fast) (default)
# 'chol' : Cholesky decomposition (fast, but unstable)
# 'sqrtm' : sqrtm (stable and slow)
#
# Returns
# -------
# r : matrix of random numbers from the multivariate normal
# distribution with the given mean and covariance matrix.
#
# The covariance must be a symmetric, semi-positive definite matrix with shape
# equal to the size of the mean. METHOD used for calculating the square root
# of COV is either svd, cholesky or sqrtm. (cholesky is fastest but least accurate.)
# When cholesky is chosen and S is not positive definite, the svd-method
# is used instead.
#
# Example
# -------
# mu = [0, 5]
# S = [[1 0.45], [0.45 0.25]]
# r = rndnormnd(S, mu, 1)
# plot(r(:,1),r(:,2),'.')
#
# d = 40; rho = 2*rand(1,d)-1;
# mu = zeros(0,d);
# S = (rho.'*rho-diag(rho.^2))+eye(d);
# r = rndnormnd(S,mu,100,'genchol')';
#
# See also
# --------
# chol, svd, sqrtm, genchol
# np.random.multivariate_normal
# '''
# sa = np.atleast_2d(cov)
# mu = np.atleast_1d(mean).ravel()
# m, n = sa.shape
# if m != n:
# raise ValueError('Covariance must be square')
# def svdfun(sa):
# u, s, vh = svd(sa, full_matrices=False)
# sqt = diagsvd(sqrt(s))
# return dot(u, dot(sqt, vh))
#
# sqrtfuns = dict(sqrtm=sqrtm, svd=svdfun, cholesky=cholesky)
# sqrtfun = sqrtfuns[method]
# std = sqrtfun(sa)
# return dot(std,random.randn(n, cases)) + mu[:,newaxis]
def rndnormnd(mean, cov, cases=1):
'''
Random vectors from a multivariate Normal distribution
Parameters
----------
mean, cov : array-like
mean and covariance, respectively.
cases : scalar integer
number of sample vectors
Returns
-------
r : matrix of random numbers from the multivariate normal
distribution with the given mean and covariance matrix.
The covariance must be a symmetric, semi-positive definite matrix with
shape equal to the size of the mean.
Example
-------
>>> mu = [0, 5]
>>> S = [[1 0.45], [0.45 0.25]]
>>> r = rndnormnd(mu, S, 1)
plot(r(:,1),r(:,2),'.')
>>> d = 40
>>> rho = 2 * np.random.rand(1,d)-1
>>> mu = zeros(d)
>>> S = (np.dot(rho.T, rho)-diag(rho.ravel()**2))+np.eye(d)
>>> r = rndnormnd(mu, S, 100)
See also
--------
np.random.multivariate_normal
'''
return np.random.multivariate_normal(mean, cov, cases)
class CovData1D(PlotData):
""" Container class for 1D covariance data objects in WAFO
Member variables
@ -147,6 +131,7 @@ class CovData1D(PlotData):
self.__dict__.update(sub_dict_select(kwds, somekeys))
self.setlabels()
def setlabels(self):
''' Set automatic title, x-,y- and z- labels
@ -155,7 +140,8 @@ class CovData1D(PlotData):
N = len(self.type)
if N == 0:
raise ValueError('Object does not appear to be initialized, it is empty!')
raise ValueError(
'Object does not appear to be initialized, it is empty!')
labels = ['', 'ACF', '']
@ -175,14 +161,8 @@ class CovData1D(PlotData):
self.labels.ylab = labels[1]
self.labels.zlab = labels[2]
## def copy(self):
## kwds = self.__dict__.copy()
## wdata = CovData1D(**kwds)
## return wdata
def tospecdata(self, rate=None, method='fft', nugget=0.0, trunc=1e-5, fast=True):
def tospecdata(self, rate=None, method='fft', nugget=0.0, trunc=1e-5,
fast=True):
'''
Computes spectral density from the auto covariance function
@ -190,14 +170,11 @@ class CovData1D(PlotData):
----------
rate = scalar, int
1,2,4,8...2^r, interpolation rate for f (default 1)
method: string
method : string
interpolation method 'stineman', 'linear', 'cubic', 'fft'
nugget = scalar, real
nugget : scalar, real
nugget effect to ensure that round off errors do not result in
negative spectral estimates. Good choice might be 10^-12.
trunc : scalar, real
truncates all spectral values where S/max(S) < trunc
0 <= trunc <1 This is to ensure that high frequency
@ -208,7 +185,7 @@ class CovData1D(PlotData):
Returns
--------
S = SpecData1D object
S : SpecData1D object
spectral density
NB! This routine requires that the covariance is evenly spaced
@ -258,29 +235,25 @@ class CovData1D(PlotData):
ftype = 'k'
if rate is None:
rate = 1 ##interpolation rate
rate = 1 # interpolation rate
else:
rate = 2 ** nextpow2(rate) ##make sure rate is a power of 2
rate = 2 ** nextpow2(rate) # make sure rate is a power of 2
## add a nugget effect to ensure that round off errors
## do not result in negative spectral estimates
# add a nugget effect to ensure that round off errors
# do not result in negative spectral estimates
acf[0] = acf[0] + nugget
n = acf.size
# embedding a circulant vector and Fourier transform
nfft = 2 ** nextpow2(2 * n - 2) if fast else 2 * n - 2
if method=='fft':
if method == 'fft':
nfft *= rate
nf = nfft / 2 ## number of frequencies
nf = nfft / 2 # number of frequencies
acf = r_[acf, zeros(nfft - 2 * n + 2), acf[n - 2:0:-1]]
Rper = (fft(acf, nfft).real).clip(0) ## periodogram
# import pylab
# pylab.semilogy(Rper)
# pylab.show()
Rper = (fft(acf, nfft).real).clip(0) # periodogram
RperMax = Rper.max()
Rper = where(Rper < trunc * RperMax, 0, Rper)
@ -320,6 +293,10 @@ class CovData1D(PlotData):
warnings.warn('Data is not uniformly sampled!')
return dt
def _is_valid_acf(self):
if self.data.argmax() != 0:
raise ValueError('ACF does not have a maximum at zero lag')
def sim(self, ns=None, cases=1, dt=None, iseed=None, derivative=False):
'''
Simulates a Gaussian process and its derivative from ACF
@ -351,8 +328,8 @@ class CovData1D(PlotData):
Gaussian process through circulant embedding of the covariance matrix.
If the ACF has a non-empty field .tr, then the transformation is
applied to the simulated data, the result is a simulation of a transformed
Gaussian process.
applied to the simulated data, the result is a simulation of a
transformed Gaussian process.
Note: The simulation may give high frequency ripple when used with a
small dt.
@ -384,15 +361,9 @@ class CovData1D(PlotData):
nugget = 0 # 10**-12
_set_seed(iseed)
self._is_valid_acf()
acf = self.data.ravel()
n = acf.size
I = acf.argmax()
if I != 0:
raise ValueError('ACF does not have a maximum at zero lag')
acf.shape = (n, 1)
dT = self.sampling_period()
@ -402,26 +373,26 @@ class CovData1D(PlotData):
if derivative:
xder = x.copy()
## add a nugget effect to ensure that round off errors
## do not result in negative spectral estimates
# add a nugget effect to ensure that round off errors
# do not result in negative spectral estimates
acf[0] = acf[0] + nugget
## Fast and exact simulation of simulation of stationary
## Gaussian process throug circulant embedding of the
## Covariance matrix
# Fast and exact simulation of simulation of stationary
# Gaussian process throug circulant embedding of the
# Covariance matrix
floatinfo = finfo(float)
if (abs(acf[-1]) > floatinfo.eps): ## assuming acf(n+1)==0
if (abs(acf[-1]) > floatinfo.eps): # assuming acf(n+1)==0
m2 = 2 * n - 1
nfft = 2 ** nextpow2(max(m2, 2 * ns))
acf = r_[acf, zeros((nfft - m2, 1)), acf[-1:0:-1, :]]
#warnings,warn('I am now assuming that ACF(k)=0 for k>MAXLAG.')
else: # # ACF(n)==0
else: # ACF(n)==0
m2 = 2 * n - 2
nfft = 2 ** nextpow2(max(m2, 2 * ns))
acf = r_[acf, zeros((nfft - m2, 1)), acf[n - 1:1:-1, :]]
##m2=2*n-2
S = fft(acf, nfft, axis=0).real ## periodogram
# m2=2*n-2
S = fft(acf, nfft, axis=0).real # periodogram
I = S.argmax()
k = flatnonzero(S < 0)
@ -438,42 +409,43 @@ class CovData1D(PlotData):
ix = flatnonzero(k > 2 * I)
if ix.size > 0:
## # truncating all oscillating values above 2 times the peak
## # frequency to zero to ensure that
## # that high frequency noise is not added to
## # the simulated timeseries.
# truncating all oscillating values above 2 times the peak
# frequency to zero to ensure that
# that high frequency noise is not added to
# the simulated timeseries.
ix0 = k[ix[0]]
S[ix0:-ix0] = 0.0
trunc = 1e-5
maxS = S[I]
k = flatnonzero(S[I:-I] < maxS * trunc)
if k.size > 0:
S[k + I] = 0.
## truncating small values to zero to ensure that
## that high frequency noise is not added to
## the simulated timeseries
# truncating small values to zero to ensure that
# that high frequency noise is not added to
# the simulated timeseries
cases1 = floor(cases / 2)
cases2 = ceil(cases / 2)
cases1 = int(cases / 2)
cases2 = int(ceil(cases / 2))
# Generate standard normal random numbers for the simulations
#randn = np.random.randn
epsi = randn(nfft, cases2) + 1j * randn(nfft, cases2)
Ssqr = sqrt(S / (nfft)) # #sqrt(S(wn)*dw )
ephat = epsi * Ssqr #[:,np.newaxis]
Ssqr = sqrt(S / (nfft)) # sqrt(S(wn)*dw )
ephat = epsi * Ssqr # [:,np.newaxis]
y = fft(ephat, nfft, axis=0)
x[:, 1:cases + 1] = hstack((y[2:ns + 2, 0:cases2].real, y[2:ns + 2, 0:cases1].imag))
x[:, 1:cases + 1] = hstack((y[2:ns + 2, 0:cases2].real,
y[2:ns + 2, 0:cases1].imag))
x[:, 0] = linspace(0, (ns - 1) * dT, ns) ##(0:dT:(dT*(np-1)))'
x[:, 0] = linspace(0, (ns - 1) * dT, ns) # (0:dT:(dT*(np-1)))'
if derivative:
Ssqr = Ssqr * r_[0:(nfft / 2 + 1), -(nfft / 2 - 1):0] * 2 * pi / nfft / dT
ephat = epsi * Ssqr #[:,newaxis]
Ssqr = Ssqr * \
r_[0:(nfft / 2 + 1), -(nfft / 2 - 1):0] * 2 * pi / nfft / dT
ephat = epsi * Ssqr # [:,newaxis]
y = fft(ephat, nfft, axis=0)
xder[:, 1:(cases + 1)] = hstack((y[2:ns + 2, 0:cases2].imag - y[2:ns + 2, 0:cases1].real))
xder[:, 1:(cases + 1)] = hstack((y[2:ns + 2, 0:cases2].imag -
y[2:ns + 2, 0:cases1].real))
xder[:, 0] = x[:, 0]
if self.tr is not None:
@ -493,37 +465,83 @@ class CovData1D(PlotData):
else:
return x
def simcond(self, xo, cases=1, method='approx', inds=None):
def _get_lag_where_acf_is_almost_zero(self):
acf = self.data.ravel()
r0 = acf[0]
n = len(acf)
sigma = sqrt(r_[0, r0 ** 2,
r0 ** 2 + 2 * np.cumsum(acf[1:n - 1] ** 2)] / n)
k = flatnonzero(np.abs(acf) > 0.1 * sigma)
if k.size > 0:
lag = min(k.max() + 3, n)
return lag
return n
def _get_acf(self, smooth=False):
self._is_valid_acf()
acf = atleast_1d(self.data).ravel()
n = self._get_lag_where_acf_is_almost_zero()
if smooth:
rwin = parzen(2 * n + 1)
return acf[:n] * rwin[n:2 * n]
else:
return acf[:n]
def _split_cov(self, sigma, i_known, i_unknown):
'''
Split covariance matrix between known/unknown observations
Returns
-------
Soo covariance between known observations
S11 = covariance between unknown observations
S1o = covariance between known and unknown obs
'''
Soo, So1 = sigma[i_known][:, i_known], sigma[i_known][:, i_unknown]
S11 = sigma[i_unknown][:, i_unknown]
return Soo, So1, S11
def _update_window(self, idx, i_unknown, num_x, num_acf,
overlap, nw, num_restored):
Nsig = len(idx)
start_max = num_x - Nsig
if (nw == 0) and (num_restored < len(i_unknown)):
# move to the next missing data
start_ix = min(i_unknown[num_restored + 1] - overlap, start_max)
else:
start_ix = min(idx[0] + num_acf, start_max)
return idx + start_ix - idx[0]
def simcond(self, xo, method='approx', i_unknown=None):
"""
Simulate values conditionally on observed known values
Parameters
----------
x : array-like
datavector including missing data.
(missing data must be NaN if inds is not given)
x : vector
timeseries including missing data.
(missing data must be NaN if i_unknown is not given)
Assumption: The covariance of x is equal to self and have the
same sample period.
cases : scalar integer
number of cases, i.e., number of columns of sample (default=1)
method : string
defining method used in the conditional simulation. Options are:
'approximate': Condition only on the closest points. Pros: quite fast
'pseudo': Use pseudo inverse to calculate conditional covariance matrix
'exact' : Exact simulation. Cons: Slow for large data sets, may not
return any result due to near singularity of the covariance matrix.
inds : integers
'approximate': Condition only on the closest points. Quite fast
'exact' : Exact simulation. Slow for large data sets, may not
return any result due to near singularity of the covariance
matrix.
i_unknown : integers
indices to spurious or missing data in x
Returns
-------
sample : ndarray
a random sample of the missing values conditioned on the observed data.
a random sample of the missing values conditioned on the observed
data.
mu, sigma : ndarray
mean and standard deviation, respectively, of the missing values
conditioned on the observed data.
Notes
-----
SIMCOND generates the missing values from x conditioned on the observed
@ -541,274 +559,141 @@ class CovData1D(PlotData):
Brodtkorb, P, Myrhaug, D, and Rue, H (2001)
"Joint distribution of wave height and wave crest velocity from
reconstructed data with application to ringing"
Int. Journal of Offshore and Polar Engineering, Vol 11, No. 1, pp 23--32
Int. Journal of Offshore and Polar Engineering, Vol 11, No. 1,
pp 23--32
Brodtkorb, P, Myrhaug, D, and Rue, H (1999)
"Joint distribution of wave height and wave crest velocity from
reconstructed data"
in Proceedings of 9th ISOPE Conference, Vol III, pp 66-73
"""
# TODO: does not work yet.
# secret methods:
# 'dec1-3': different decomposing algorithm's
# which is only correct for a variables
# having the Markov property
# Cons: 3 is not correct at all, but seems to give
# a reasonable result
# Pros: 1 is slow, 2 is quite fast and 3 is very fast
# Note: (mu1oStd is not given for method ='dec3')
compute_sigma = True
x = atleast_1d(xo).ravel()
acf = atleast_1d(self.data).ravel()
acf = self._get_acf()
num_x = len(x)
num_acf = len(acf)
if not i_unknown is None:
x[i_unknown] = nan
i_unknown = flatnonzero(isnan(x))
num_unknown = len(i_unknown)
mu1o = zeros((num_unknown,))
mu1o_std = zeros((num_unknown,))
sample = zeros((num_unknown,))
if num_unknown == 0:
warnings.warn('No missing data, no point to continue.')
return sample, mu1o, mu1o_std
if num_unknown == num_x:
warnings.warn('All data missing, returning sample from' +
' the apriori distribution.')
mu1o_std = ones(num_unknown) * sqrt(acf[0])
return self.sim(ns=num_unknown, cases=1)[:, 1], mu1o, mu1o_std
i_known = flatnonzero(1 - isnan(x))
if method.startswith('exac'):
# exact but slow. It also may not return any result
if num_acf > 0.3 * num_x:
Sigma = toeplitz(hstack((acf, zeros(num_x - num_acf))))
else:
acf[0] = acf[0] * 1.00001
Sigma = sptoeplitz(hstack((acf, zeros(num_x - num_acf))))
Soo, So1, S11 = self._split_cov(Sigma, i_known, i_unknown)
if issparse(Sigma):
So1 = So1.todense()
S11 = S11.todense()
S1o_Sooinv = spsolve(Soo + Soo.T, 2 * So1).T
else:
Sooinv_So1, _res, _rank, _s = lstsq(Soo + Soo.T, 2 * So1,
cond=1e-4)
S1o_Sooinv = Sooinv_So1.T
mu1o = S1o_Sooinv.dot(x[i_known])
Sigma1o = S11 - S1o_Sooinv.dot(So1)
if (diag(Sigma1o) < 0).any():
raise ValueError('Failed to converge to a solution')
N = len(x)
n = len(acf)
mu1o_std = sqrt(diag(Sigma1o))
sample[:] = rndnormnd(mu1o, Sigma1o, cases=1).ravel()
i = acf.argmax()
if i != 0:
raise ValueError('This is not a valid ACF!!')
if not inds is None:
x[inds] = nan
inds = where(isnan(x))[0] #indices to the unknown observations
Ns = len(inds) # # missing values
if Ns == 0:
warnings.warn('No missing data, unable to continue.')
return xo, zeros(Ns), zeros(Ns)
#end
if Ns == N:# simulated surface from the apriori distribution
txt = '''All data missing,
returning sample from the unconditional distribution.'''
warnings.warn(txt)
return self.sim(ns=N, cases=cases), zeros(Ns), zeros(Ns)
indg = where(1 - isnan(x))[0] #indices to the known observations
#initializing variables
mu1o = zeros(Ns, 1)
mu1o_std = mu1o
sample = zeros((Ns, cases))
if method[0] == 'd':
# simulated surface from the apriori distribution
xs = self.sim(ns=N, cases=cases)
mu1os = zeros((Ns, cases))
if method.startswith('dec1'):
# only correct for variables having the Markov property
# but still seems to give a reasonable answer. Slow procedure.
Sigma = sptoeplitz(hstack((acf, zeros(N - n))))
#Soo=Sigma(~inds,~inds); # covariance between known observations
#S11=Sigma(inds,inds); # covariance between unknown observations
#S1o=Sigma(inds,~inds);# covariance between known and unknown observations
#tmp=S1o*pinv(full(Soo));
#tmp=S1o/Soo; # this is time consuming if Soo large
tmp = 2 * Sigma[inds, indg] / (Sigma[indg, indg] + Sigma[indg, indg].T)
if compute_sigma:
#standard deviation of the expected surface
#mu1o_std=sqrt(diag(S11-tmp*S1o'));
mu1o_std = sqrt(diag(Sigma[inds, inds] - tmp * Sigma[indg, inds]))
#expected surface conditioned on the known observations from x
mu1o = tmp * x[indg]
#expected surface conditioned on the known observations from xs
mu1os = tmp * (xs[indg, :])
# sampled surface conditioned on the known observations
sample = mu1o + xs[inds, :] - mu1os
elif method.startswith('dec2'):
# only correct for variables having the Markov property
# but still seems to give a reasonable answer
# approximating the expected surfaces conditioned on
# the known observations from x and xs by only using the closest points
Sigma = sptoeplitz(hstack((acf, zeros(n))))
n2 = int(floor(n / 2))
idx = r_[0:2 * n] + max(0, inds[0] - n2) # indices to the points used
tmpinds = zeros(N, dtype=bool)
tmpinds[inds] = True # temporary storage of indices to missing points
tinds = where(tmpinds[idx])[0] # indices to the points used
tindg = where(1 - tmpinds[idx])[0]
ns = len(tinds); # number of missing data in the interval
nprev = 0; # number of previously simulated points
xsinds = xs[inds, :]
while ns > 0:
tmp = 2 * Sigma[tinds, tindg] / (Sigma[tindg, tindg] + Sigma[tindg, tindg].T)
if compute_sigma:
#standard deviation of the expected surface
#mu1o_std=sqrt(diag(S11-tmp*S1o'));
ix = slice(nprev + 1, nprev + ns + 1)
mu1o_std[ix] = max(mu1o_std[ix],
sqrt(diag(Sigma[tinds, tinds] - tmp * Sigma[tindg, tinds])))
#end
#expected surface conditioned on the closest known observations
# from x and xs2
mu1o[(nprev + 1):(nprev + ns + 1)] = tmp * x[idx[tindg]]
mu1os[(nprev + 1):(nprev + ns + 1), :] = tmp * xs[idx[tindg], :]
if idx[-1] == N - 1:#
ns = 0 # no more points to simulate
else:
# updating by putting expected surface into x
x[idx[tinds]] = mu1o[(nprev + 1):(nprev + ns + 1)]
xs[idx[tinds]] = mu1os[(nprev + 1):(nprev + ns + 1)]
elif method.startswith('appr'):
# approximating by only condition on the closest points
nw = sum(tmpinds[idx[-n2:]])# # data which we want to simulate once
tmpinds[idx[:-n2]] = False # removing indices to data ..
# which has been simulated
nprev = nprev + ns - nw # update # points simulated so far
Nsig = min(2 * num_acf, num_x)
if (nw == 0) and (nprev < Ns):
idx = r_[0:2 * n] + (inds[nprev + 1] - n2) # move to the next missing data
else:
idx = idx + n
#end
tmp = N - idx[-1]
if tmp < 0: # checking if tmp exceeds the limits
idx = idx + tmp
#end
# find new interval with missing data
tinds = where(tmpinds[idx])[0]
tindg = where(1 - tmpinds[idx])[0]
ns = len(tinds);# # missing data
#end
#end
# sampled surface conditioned on the known observations
sample = mu1o + (xsinds - mu1os)
elif method.startswith('dec3'):
# this is not correct for even for variables having the
# Markov property but still seems to give a reasonable answer
# a quasi approach approximating the expected surfaces conditioned on
# the known observations from x and xs with a spline
mu1o = interp1(indg, x[indg], inds, 'spline')
mu1os = interp1(indg, xs[indg, :], inds, 'spline')
# sampled surface conditioned on the known observations
sample = mu1o + (xs[inds, :] - mu1os)
elif method.startswith('exac') or method.startswith('pseu'):
# exact but slow. It also may not return any result
Sigma = sptoeplitz(hstack((acf, zeros(N - n))))
#Soo=Sigma(~inds,~inds); # covariance between known observations
#S11=Sigma(inds,inds); # covariance between unknown observations
#S1o=Sigma(inds,~inds);# covariance between known and unknown observations
#tmp=S1o/Soo; # this is time consuming if Soo large
if method[0] == 'e': #exact
tmp = 2 * Sigma[inds, indg] / (Sigma[indg, indg] + Sigma[indg, indg].T);
else: # approximate the inverse with pseudo inverse
tmp = dot(Sigma[inds, indg], pinv(Sigma[indg, indg]))
#end
#expected surface conditioned on the known observations from x
mu1o = dot(tmp, x[indg])
# Covariance conditioned on the known observations
Sigma1o = Sigma[inds, inds] - tmp * Sigma[indg, inds]
#sample conditioned on the known observations from x
sample = random.multivariate_normal(mu1o, Sigma1o, cases)
#rndnormnd(mu1o,Sigma1o,cases )
if compute_sigma:
#standard deviation of the expected surface
mu1o_std = sqrt(diag(Sigma1o));
#end
Sigma = toeplitz(hstack((acf, zeros(Nsig - num_acf))))
overlap = int(Nsig / 4)
# indices to the points used
idx = r_[0:Nsig] + max(0, min(i_unknown[0] - overlap, num_x - Nsig))
mask_unknown = zeros(num_x, dtype=bool)
# temporary storage of indices to missing points
mask_unknown[i_unknown] = True
t_unknown = where(mask_unknown[idx])[0]
t_known = where(1 - mask_unknown[idx])[0]
ns = len(t_unknown) # number of missing data in the interval
elif method.startswith('appr'):
# approximating by only condition on
# the closest points
# checking approximately how many lags we need in order to
# ensure conditional independence
# using that the inverse of the circulant covariance matrix has
# approximately the same bandstructure as the inverse of the
# covariance matrix
Nsig = 2 * n;
Sigma = sptoeplitz(hstack((acf, zeros(Nsig - n))))
n2 = floor(Nsig / 4)
idx = r_[0:Nsig] + max(0, inds[0] - n2) # indices to the points used
tmpinds = zeros(N, dtype=bool)
tmpinds[inds] = True # temporary storage of indices to missing points
tinds = where(tmpinds[idx])[0] # indices to the points used
tindg = where(1 - tmpinds[idx])[0]
ns = len(tinds) # number of missing data in the interval
nprev = 0 # number of previously simulated points
x2 = x
num_restored = 0 # number of previously simulated points
x2 = x.copy()
while ns > 0:
#make sure MATLAB uses a symmetric matrix solver
tmp = 2 * Sigma[tinds, tindg] / (Sigma[tindg, tindg] + Sigma[tindg, tindg].T)
Sigma1o = Sigma[tinds, tinds] - tmp * Sigma[tindg, tinds]
if compute_sigma:
#standard deviation of the expected surface
#mu1o_std=sqrt(diag(S11-tmp*S1o'));
mu1o_std[(nprev + 1):(nprev + ns + 1)] = max(mu1o_std[(nprev + 1):(nprev + ns)] ,
sqrt(diag(Sigma1o)))
#end
#expected surface conditioned on the closest known observations from x
mu1o[(nprev + 1):(nprev + ns + 1)] = tmp * x2[idx[tindg]]
#sample conditioned on the known observations from x
sample[(nprev + 1):(nprev + ns + 1), :] = rndnormnd(tmp * x[idx[tindg]], Sigma1o, cases)
if idx[-1] == N - 1:
ns = 0 # no more points to simulate
Soo, So1, S11 = self._split_cov(Sigma, t_known, t_unknown)
if issparse(Soo):
So1 = So1.todense()
S11 = S11.todense()
S1o_Sooinv = spsolve(Soo + Soo.T, 2 * So1).T
else:
# updating
x2[idx[tinds]] = mu1o[(nprev + 1):(nprev + ns + 1)] #expected surface
x[idx[tinds]] = sample[(nprev + 1):(nprev + ns + 1)]#sampled surface
nw = sum(tmpinds[idx[-n2::]] == True)# # data we want to simulate once more
tmpinds[idx[:-n2]] = False # removing indices to data ..
# which has been simulated
nprev = nprev + ns - nw # update # points simulated so far
if (nw == 0) and (nprev < Ns):
idx = r_[0:Nsig] + (inds[nprev + 1] - n2) # move to the next missing data
Sooinv_So1, _res, _rank, _s = lstsq(Soo + Soo.T, 2 * So1,
cond=1e-4)
S1o_Sooinv = Sooinv_So1.T
Sigma1o = S11 - S1o_Sooinv.dot(So1)
if (diag(Sigma1o) < 0).any():
raise ValueError('Failed to converge to a solution')
ix = slice((num_restored), (num_restored + ns))
# standard deviation of the expected surface
mu1o_std[ix] = np.maximum(mu1o_std[ix], sqrt(diag(Sigma1o)))
# expected surface conditioned on the closest known
# observations from x
mu1o[ix] = S1o_Sooinv.dot(x2[idx[t_known]])
# sample conditioned on the known observations from x
mu1os = S1o_Sooinv.dot(x[idx[t_known]])
sample[ix] = rndnormnd(mu1os, Sigma1o, cases=1)
if idx[-1] == num_x - 1:
ns = 0 # no more points to simulate
else:
idx = idx + n
#end
tmp = N - idx[-1]
if tmp < 0: # checking if tmp exceeds the limits
idx = idx + tmp
#end
x2[idx[t_unknown]] = mu1o[ix] # expected surface
x[idx[t_unknown]] = sample[ix] # sampled surface
# removing indices to data which has been simulated
mask_unknown[idx[:-overlap]] = False
# data we want to simulate once more
nw = sum(mask_unknown[idx[-overlap:]] == True)
num_restored += ns - nw # update # points simulated so far
idx = self._update_window(idx, i_unknown, num_x, num_acf,
overlap, nw, num_restored)
# find new interval with missing data
tinds = where(tmpinds[idx])[0]
tindg = where(1 - tmpinds[idx])[0]
ns = len(tinds);# # missing data in the interval
#end
#end
#end
return sample
# plot(find(~inds),x(~inds),'.')
# hold on,
# ind=find(inds);
# plot(ind,mu1o ,'*')
# plot(ind,sample,'r+')
# #mu1o_std
# plot(ind,[mu1o-2*mu1o_std mu1o+2*mu1o_std ] ,'d')
# #plot(xs),plot(ind,mu1os,'r*')
# hold off
# legend('observed values','mu1o','sampled values','2 stdev')
# #axis([770 850 -1 1])
# #axis([1300 1325 -1 1])
t_unknown = flatnonzero(mask_unknown[idx])
t_known = flatnonzero(1 - mask_unknown[idx])
ns = len(t_unknown) # # missing data in the interval
return sample, mu1o, mu1o_std
def sptoeplitz(x):
k = where(x.ravel())[0]
k = flatnonzero(x)
n = len(x)
if len(k) > 0.3 * n:
return toeplitz(x)
else:
spdiags = sparse.dia_matrix
data = x[k].reshape(-1, 1).repeat(n, axis= -1)
data = x[k].reshape(-1, 1).repeat(n, axis=-1)
offsets = k
y = spdiags((data, offsets), shape=(n, n))
if k[0] == 0:
offsets = k[1::]
data = data[1::, :]
return y + spdiags((data, -offsets), shape=(n, n))
t = y + spdiags((data, -offsets), shape=(n, n))
return t.tocsr()
def _test_covdata():
import wafo.data
@ -817,20 +702,35 @@ def _test_covdata():
rf = ts.tocovdata(lag=150)
rf.plot()
def main():
import wafo.spectrum.models as sm
import matplotlib
matplotlib.interactive(True)
Sj = sm.Jonswap()
S = Sj.tospecdata() #Make spec
S = Sj.tospecdata() # Make spec
S.plot()
R = S.tocovdata()
R = S.tocovdata(rate=3)
R.plot()
#x = R.sim(ns=1000,dt=0.2)
x = R.sim(ns=1024 * 4)
inds = np.hstack((21 + np.arange(20),
1000 + np.arange(20),
1024 * 4 - 21 + np.arange(20)))
sample, mu1o, mu1o_std = R.simcond(x[:, 1], method='approx', i_unknown=inds)
import matplotlib.pyplot as plt
#inds = np.atleast_2d(inds).reshape((-1,1))
plt.plot(x[:, 1], 'k.', label='observed values')
plt.plot(inds, mu1o, '*', label='mu1o')
plt.plot(inds, sample.ravel(), 'r+', label='samples')
plt.plot(inds, mu1o - 2 * mu1o_std, 'r',
inds, mu1o + 2 * mu1o_std, 'r', label='2 stdev')
plt.legend()
plt.show('hold')
if __name__ == '__main__':
if True: #False : #
if False: # True: #
import doctest
doctest.testmod()
else:

@ -3,7 +3,8 @@ from scipy.fftpack import dct as _dct
from scipy.fftpack import idct as _idct
__all__ = ['dct', 'idct', 'dctn', 'idctn']
def dct(x, type=2, n=None, axis=-1, norm='ortho'): #@ReservedAssignment
def dct(x, type=2, n=None, axis=-1, norm='ortho'): # @ReservedAssignment
'''
Return the Discrete Cosine Transform of arbitrary type sequence x.
@ -99,10 +100,13 @@ def dct(x, type=2, n=None, axis=-1, norm='ortho'): #@ReservedAssignment
'''
farr = np.asfarray
if np.iscomplex(x).any():
return _dct(farr(x.real), type, n, axis, norm) + 1j*_dct(farr(x.imag), type, n, axis, norm)
return _dct(farr(x.real), type, n, axis, norm) + \
1j * _dct(farr(x.imag), type, n, axis, norm)
else:
return _dct(farr(x), type, n, axis, norm)
def idct(x, type=2, n=None, axis=-1, norm='ortho'): #@ReservedAssignment
def idct(x, type=2, n=None, axis=-1, norm='ortho'): # @ReservedAssignment
'''
Return the Inverse Discrete Cosine Transform of an arbitrary type sequence.
@ -141,10 +145,13 @@ def idct(x, type=2, n=None, axis=-1, norm='ortho'): #@ReservedAssignment
'''
farr = np.asarray
if np.iscomplex(x).any():
return _idct(farr(x.real), type, n, axis, norm) + 1j*_idct(farr(x.imag), type, n, axis, norm)
return _idct(farr(x.real), type, n, axis, norm) + \
1j * _idct(farr(x.imag), type, n, axis, norm)
else:
return _idct(farr(x), type, n, axis, norm)
def dctn(x, type=2, axis=None, norm='ortho'): #@ReservedAssignment
def dctn(x, type=2, axis=None, norm='ortho'): # @ReservedAssignment
'''
DCTN N-D discrete cosine transform.
@ -189,65 +196,68 @@ def dctn(x, type=2, axis=None, norm='ortho'): #@ReservedAssignment
if axis is None:
y = y.squeeze() # Working across singleton dimensions is useless
ndim = y.ndim
isvector = max(shape0)==y.size
isvector = max(shape0) == y.size
if isvector:
if ndim==1:
if ndim == 1:
y = np.atleast_2d(y)
y = y.T
elif y.shape[0]==1:
if axis==0:
elif y.shape[0] == 1:
if axis == 0:
return x
elif axis==1:
axis=0
elif axis == 1:
axis = 0
y = y.T
elif axis==1:
elif axis == 1:
return y
if np.iscomplex(y).any():
y = dctn(y.real, type, axis, norm) + 1j*dctn(y.imag, type, axis, norm)
y = dctn(y.real, type, axis, norm) + 1j * \
dctn(y.imag, type, axis, norm)
else:
y = np.asfarray(y)
for dim in range(ndim):
y = y.transpose(np.roll(range(y.ndim), -1))
#y = shiftdim(y,1)
if axis is not None and dim!=axis:
if axis is not None and dim != axis:
continue
y = _dct(y, type, norm=norm)
return y.reshape(shape0)
def idctn(x, type=2, axis=None, norm='ortho'): #@ReservedAssignment
def idctn(x, type=2, axis=None, norm='ortho'): # @ReservedAssignment
y = np.atleast_1d(x)
shape0 = y.shape
if axis is None:
y = y.squeeze() # Working across singleton dimensions is useless
ndim = y.ndim
isvector = max(shape0)==y.size
isvector = max(shape0) == y.size
if isvector:
if ndim==1:
if ndim == 1:
y = np.atleast_2d(y)
y = y.T
elif y.shape[0]==1:
if axis==0:
elif y.shape[0] == 1:
if axis == 0:
return x
elif axis==1:
axis=0
elif axis == 1:
axis = 0
y = y.T
elif axis==1:
elif axis == 1:
return y
if np.iscomplex(y).any():
y = idctn(y.real, type, axis, norm) + 1j*idctn(y.imag, type, axis, norm)
y = idctn(y.real, type, axis, norm) + 1j * \
idctn(y.imag, type, axis, norm)
else:
y = np.asfarray(y)
for dim in range(ndim):
y = y.transpose(np.roll(range(y.ndim), -1))
#y = shiftdim(y,1)
if axis is not None and dim!=axis:
if axis is not None and dim != axis:
continue
y = _idct(y, type, norm=norm)
return y.reshape(shape0)
#def dct(x, n=None):
# def dct(x, n=None):
# """
# Discrete Cosine Transform
#
@ -297,7 +307,7 @@ def idctn(x, type=2, axis=None, norm='ortho'): #@ReservedAssignment
# else:
# return y
#
#def idct(x, n=None):
# def idct(x, n=None):
# """
# Inverse Discrete Cosine Transform
#
@ -345,7 +355,8 @@ def idctn(x, type=2, axis=None, norm='ortho'): #@ReservedAssignment
# y[..., ::2] = yp[..., :n / 2]
# y[..., ::-2] = yp[..., n / 2::]
# else:
# yp = ifft(np.hstack((xx, np.zeros_like(xx[..., 0]), np.conj(xx[..., :0:-1]))))
# yp = ifft(np.hstack((xx, np.zeros_like(xx[..., 0]),
# np.conj(xx[..., :0:-1]))))
# y = yp[..., :n]
#
# if real_x:
@ -353,7 +364,7 @@ def idctn(x, type=2, axis=None, norm='ortho'): #@ReservedAssignment
# else:
# return y
#
#def dctn(y, axis=None, w=None):
# def dctn(y, axis=None, w=None):
# '''
# DCTN N-D discrete cosine transform.
#
@ -403,16 +414,16 @@ def idctn(x, type=2, axis=None, norm='ortho'): #@ReservedAssignment
# if dimy==1:
# y = np.atleast_2d(y)
# y = y.T
# # Some modifications are required if Y is a vector
## if isvector(y):
## if y.shape[0]==1:
## if axis==0:
## return y, None
## elif axis==1:
## axis=0
# Some modifications are required if Y is a vector
# if isvector(y):
# if y.shape[0]==1:
# if axis==0:
# return y, None
# elif axis==1:
# axis=0
## y = y.T
## elif axis==1:
## return y, None
# elif axis==1:
# return y, None
#
# if w is None:
# w = [0,] * dimy
@ -420,17 +431,17 @@ def idctn(x, type=2, axis=None, norm='ortho'): #@ReservedAssignment
# if axis is not None and dim!=axis:
# continue
# n = (dimy==1)*y.size + (dimy>1)*shape0[dim]
# #w{dim} = exp(1i*(0:n-1)'*pi/2/n);
# w{dim} = exp(1i*(0:n-1)'*pi/2/n);
# w[dim] = np.exp(1j * np.arange(n) * np.pi / (2 * n))
#
# # --- DCT algorithm ---
# --- DCT algorithm ---
# if np.iscomplex(y).any():
# y = dctn(np.real(y),axis,w) + 1j*dctn(np.imag(y),axis,w)
# else:
# for dim in range(dimy):
# y = shiftdim(y,1)
# if axis is not None and dim!=axis:
# #y = shiftdim(y, 1)
# y = shiftdim(y, 1)
# continue
# siz = y.shape
# n = siz[-1]
@ -441,12 +452,12 @@ def idctn(x, type=2, axis=None, norm='ortho'): #@ReservedAssignment
# y[:,0] = y[:,0]/np.sqrt(2)
# y = y.reshape(siz)
#
# #end
# #end
# end
# end
#
# return y.reshape(shape0), w
#
#def idctn(y, axis=None, w=None):
# def idctn(y, axis=None, w=None):
# '''
# IDCTN N-D inverse discrete cosine transform.
# X = IDCTN(Y) inverts the N-D DCT transform, returning the original
@ -510,16 +521,16 @@ def idctn(x, type=2, axis=None, norm='ortho'): #@ReservedAssignment
# if dimy==1:
# y = np.atleast_2d(y)
# y = y.T
# # Some modifications are required if Y is a vector
## if isvector(y):
## if y.shape[0]==1:
## if axis==0:
## return y, None
## elif axis==1:
## axis=0
# Some modifications are required if Y is a vector
# if isvector(y):
# if y.shape[0]==1:
# if axis==0:
# return y, None
# elif axis==1:
# axis=0
## y = y.T
## elif axis==1:
## return y, None
# elif axis==1:
# return y, None
##
#
#
@ -529,16 +540,16 @@ def idctn(x, type=2, axis=None, norm='ortho'): #@ReservedAssignment
# if axis is not None and dim!=axis:
# continue
# n = (dimy==1)*y.size + (dimy>1)*shape0[dim]
# #w{dim} = exp(1i*(0:n-1)'*pi/2/n);
# w{dim} = exp(1i*(0:n-1)'*pi/2/n);
# w[dim] = np.exp(1j * np.arange(n) * np.pi / (2 * n))
# # --- IDCT algorithm ---
# --- IDCT algorithm ---
# if np.iscomplex(y).any():
# y = np.complex(idctn(np.real(y),axis,w),idctn(np.imag(y),axis,w))
# else:
# for dim in range(dimy):
# y = shiftdim(y,1)
# if axis is not None and dim!=axis:
# #y = shiftdim(y, 1)
# y = shiftdim(y, 1)
# continue
# siz = y.shape
# n = siz[-1]
@ -560,7 +571,6 @@ def idctn(x, type=2, axis=None, norm='ortho'): #@ReservedAssignment
# return y, w
def no_leading_ones(x):
first = 0
for i, xi in enumerate(x):
@ -569,6 +579,7 @@ def no_leading_ones(x):
break
return x[first:]
def shiftdim(x, n=None):
'''
Shift dimensions
@ -598,13 +609,14 @@ def shiftdim(x, n=None):
'''
if n is None:
return x.reshape(no_leading_ones(x.shape))
elif n>=0:
elif n >= 0:
return x.transpose(np.roll(range(x.ndim), -n))
else:
return x.reshape((1,)*-n+x.shape)
return x.reshape((1,) * -n + x.shape)
def test_dctn():
a = np.arange(12) #.reshape((3,-1))
a = np.arange(12) # .reshape((3,-1))
print('a = ', a)
print(' ')
y = dct(a)
@ -639,11 +651,12 @@ def test_dctn():
# print(xn1)
def test_docstrings():
import doctest
doctest.testmod()
print('Testing docstrings in %s' % __file__)
doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
if __name__ == '__main__':
test_docstrings()
#test_dctn()
# test_dctn()

@ -20,6 +20,8 @@ or
"""
def wave_amplitudes():
r"""
Wave amplitudes and heights definitions and nomenclature
@ -55,6 +57,7 @@ def wave_amplitudes():
"""
print(wave_amplitudes.__doc__)
def crossings():
r"""
Level v crossing definitions and nomenclature
@ -99,6 +102,7 @@ def crossings():
"""
print(crossings.__doc__)
def cycle_pairs():
r"""
Cycle pairs definitions and numenclature
@ -116,6 +120,7 @@ def cycle_pairs():
"""
print(cycle_pairs.__doc__)
def wave_periods():
r"""
Wave periods (lengths) definitions and nomenclature
@ -203,6 +208,8 @@ def wave_periods():
turning_points
"""
print(wave_periods.__doc__)
def turning_points():
r"""
Turning points definitions and numenclature
@ -238,6 +245,8 @@ def turning_points():
"""
print(turning_points.__doc__)
def waves():
r"""
Wave definitions and nomenclature

@ -1,17 +1,18 @@
from pylab import subplot, plot, title, savefig, figure, arange, sin, random #@UnresolvedImport
# @UnresolvedImport
from pylab import subplot, plot, title, savefig, figure, arange, sin, random
from sg_filter import calc_coeff, smooth
figure(figsize=(7,12))
figure(figsize=(7, 12))
# generate chirp signal
tvec = arange(0, 6.28, .02)
signal = sin(tvec*(2.0+tvec))
signal = sin(tvec * (2.0 + tvec))
# add noise to signal
noise = random.normal(size=signal.shape)
signal += (2000.+.15 * noise)
signal += (2000. + .15 * noise)
# plot signal
subplot(311)
@ -36,8 +37,3 @@ title('smoothed derivative of signal')
# show plot
savefig("savitzky.png")

@ -4,10 +4,10 @@ Created on 20. jan. 2011
@author: pab
'''
import numpy as np
from numpy import exp
from wafo.misc import meshgrid
from numpy import exp, meshgrid
__all__ = ['peaks', 'humps', 'magic']
def magic(n):
'''
Return magic square for n of any orders > 2.
@ -36,49 +36,51 @@ def magic(n):
[30, 5, 34, 12, 14, 16],
[ 4, 36, 29, 13, 18, 11]])
'''
if (n<3):
if (n < 3):
raise ValueError('n must be greater than 2.')
if np.mod(n,2)==1: # odd order
if np.mod(n, 2) == 1: # odd order
ix = np.arange(n) + 1
J, I = np.meshgrid(ix, ix)
A = np.mod(I + J - (n + 3) / 2, n)
B = np.mod(I + 2 * J - 2, n)
M = n * A + B + 1
elif np.mod(n,4)==0: # doubly even order
M = np.arange(1,n*n+1).reshape(n,n)
ix = np.mod(np.arange(n) + 1,4)//2
elif np.mod(n, 4) == 0: # doubly even order
M = np.arange(1, n * n + 1).reshape(n, n)
ix = np.mod(np.arange(n) + 1, 4) // 2
J, I = np.meshgrid(ix, ix)
iz = np.flatnonzero(I==J)
M.put(iz, n*n+1-M.flat[iz])
iz = np.flatnonzero(I == J)
M.put(iz, n * n + 1 - M.flat[iz])
else: # singly even order
p = n//2
p = n // 2
M0 = magic(p)
M = np.hstack((np.vstack((M0, M0+3*p*p)),np.vstack((M0+2*p*p, M0+p*p))))
M = np.hstack((np.vstack((M0, M0 + 3 * p * p)),
np.vstack((M0 + 2 * p * p, M0 + p * p))))
if n>2:
k = (n-2)//4
Jvec = np.hstack((np.arange(k), np.arange(n-k+1, n)))
if n > 2:
k = (n - 2) // 4
Jvec = np.hstack((np.arange(k), np.arange(n - k + 1, n)))
for i in range(p):
for j in Jvec:
temp = M[i][j]
M[i][j]=M[i+p][j]
M[i+p][j] = temp
M[i][j] = M[i + p][j]
M[i + p][j] = temp
i=k
j=0
temp = M[i][j];
M[i][j] = M[i+p][j]
M[i+p][j] = temp;
i = k
j = 0
temp = M[i][j]
M[i][j] = M[i + p][j]
M[i + p][j] = temp
j=i
temp=M[i+p][j]
M[i+p][j]=M[i][j]
M[i][j]=temp
j = i
temp = M[i + p][j]
M[i + p][j] = M[i][j]
M[i][j] = temp
return M
def peaks(x=None, y=None, n=51):
'''
Return the "well" known MatLab (R) peaks function
@ -105,6 +107,7 @@ def peaks(x=None, y=None, n=51):
return x1, y1, z
def humps(x=None):
'''
Computes a function that has three roots, and some humps.
@ -122,11 +125,14 @@ def humps(x=None):
else:
y = np.asarray(x)
return 1.0 / ((y - 0.3) ** 2 + 0.01) + 1.0 / ((y - 0.9) ** 2 + 0.04) + 2 * y - 5.2
return 1.0 / ((y - 0.3) ** 2 + 0.01) + 1.0 / ((y - 0.9) ** 2 + 0.04) + \
2 * y - 5.2
def test_docstrings():
import doctest
doctest.testmod()
print('Testing docstrings in %s' % __file__)
doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
if __name__ == '__main__':
test_docstrings()

@ -10,16 +10,18 @@ import warnings
import numpy as np
from wafo.plotbackend import plotbackend
from matplotlib import mlab
__all__ = ['cltext', 'epcolor', 'tallibing', 'test_docstrings']
__all__ = ['cltext', 'tallibing', 'test_docstrings']
_TALLIBING_GID = 'TALLIBING'
_CLTEXT_GID = 'CLTEXT'
def _matchfun(x, gidtxt):
if hasattr(x, 'get_gid'):
return x.get_gid() == gidtxt
return False
def delete_text_object(gidtxt, figure=None, axis=None, verbose=False):
'''
Delete all text objects matching the gidtxt if it exists
@ -37,23 +39,27 @@ def delete_text_object(gidtxt, figure=None, axis=None, verbose=False):
figure = plotbackend.gcf()
if axis is None:
axis = figure.gca()
lmatchfun = lambda x : _matchfun(x, gidtxt)
lmatchfun = lambda x: _matchfun(x, gidtxt)
objs = axis.findobj(lmatchfun)
for obj in objs:
try:
axis.texts.remove(obj)
except:
if verbose:
warnings.warn('Tried to delete a non-existing %s from axis' % gidtxt)
warnings.warn(
'Tried to delete a non-existing %s from axis' % gidtxt)
objs = figure.findobj(lmatchfun)
for obj in objs:
try:
figure.texts.remove(obj)
except:
if verbose:
warnings.warn('Tried to delete a non-existing %s from figure' % gidtxt)
warnings.warn(
'Tried to delete a non-existing %s from figure' % gidtxt)
def cltext(levels, percent=False, n=4, xs=0.036, ys=0.94, zs=0, figure=None, axis=None):
def cltext(levels, percent=False, n=4, xs=0.036, ys=0.94, zs=0, figure=None,
axis=None):
'''
Places contour level text in the current window
@ -102,7 +108,8 @@ def cltext(levels, percent=False, n=4, xs=0.036, ys=0.94, zs=0, figure=None, axi
>>> h = wg.cltext(h.levels)
>>> plt.show()
'''
# TODO : Make it work like legend does (but without the box): include position options etc...
# TODO : Make it work like legend does (but without the box): include
# position options etc...
if figure is None:
figure = plotbackend.gcf()
if axis is None:
@ -110,7 +117,6 @@ def cltext(levels, percent=False, n=4, xs=0.036, ys=0.94, zs=0, figure=None, axi
clevels = np.atleast_1d(levels)
axpos = axis.get_position()
xint = axpos.intervalx
yint = axpos.intervaly
@ -125,20 +131,20 @@ def cltext(levels, percent=False, n=4, xs=0.036, ys=0.94, zs=0, figure=None, axi
delta_y = charHeight
if percent:
titletxt = 'Level curves enclosing:';
titletxt = 'Level curves enclosing:'
else:
titletxt = 'Level curves at:';
titletxt = 'Level curves at:'
format_ = '%0.' + ('%d' % n) + 'g\n'
cltxt = ''.join([format_ % level for level in clevels.tolist()])
titleProp = dict(gid=_CLTEXT_GID, horizontalalignment='left',
verticalalignment='center', fontweight='bold', axes=axis) #
verticalalignment='center', fontweight='bold', axes=axis)
ha1 = figure.text(xss, yss, titletxt, **titleProp)
yss -= delta_y;
yss -= delta_y
txtProp = dict(gid=_CLTEXT_GID, horizontalalignment='left',
verticalalignment='top', axes=axis)
@ -146,18 +152,31 @@ def cltext(levels, percent=False, n=4, xs=0.036, ys=0.94, zs=0, figure=None, axi
plotbackend.draw_if_interactive()
return ha1, ha2
def tallibing(x, y, n, **kwds):
def tallibing(*args, **kwds):
'''
TALLIBING Display numbers on field-plot
CALL h=tallibing(x,y,n,size,color)
x,y = position matrices
n = the corresponding matrix of the values to be written
Parameters
----------
x, y : array
position matrices
n : array
corresponding matrix of the values to be written
(non-integers are rounded)
size = font size (optional) (default=8)
color = color of text (optional) (default='white')
h = column-vector of handles to TEXT objects
mid_points : bool (default True)
data-point-positions are in the middle of bins instead of the corners
size : int, (default=8)
font size (optional)
color : str, (default='white')
color of text (optional)
Returns
-------
h : list
handles to TEXT objects
TALLIBING writes the numbers in a 2D array as text at the positions
given by the x and y coordinate matrices.
@ -169,114 +188,80 @@ def tallibing(x, y, n, **kwds):
>>> import wafo.graphutil as wg
>>> import wafo.demos as wd
>>> [x,y,z] = wd.peaks(n=20)
>>> h0 = wg.epcolor(x,y,z)
>>> h0 = wg.pcolor(x,y,z)
>>> h1 = wg.tallibing(x,y,z)
pcolor(x,y,z); shading interp;
See also
--------
text
'''
axis = kwds.pop('axis',None)
axis = kwds.pop('axis', None)
if axis is None:
axis = plotbackend.gca()
x, y, n = np.atleast_1d(x, y, n)
x, y, n = _parse_data(*args, **kwds)
if mlab.isvector(x) or mlab.isvector(y):
x, y = np.meshgrid(x,y)
x, y = np.meshgrid(x, y)
x = x.ravel()
y = y.ravel()
n = n.ravel()
n = np.round(n)
# delete tallibing object if it exists
delete_text_object(_TALLIBING_GID, axis=axis)
txtProp = dict(gid=_TALLIBING_GID, size=8, color='w', horizontalalignment='center',
txtProp = dict(gid=_TALLIBING_GID, size=8, color='w',
horizontalalignment='center',
verticalalignment='center', fontweight='demi', axes=axis)
txtProp.update(**kwds)
h = []
for xi,yi, ni in zip(x,y,n):
for xi, yi, ni in zip(x.ravel(), y.ravel(), n.ravel()):
if ni:
h.append(axis.text(xi, yi, str(ni), **txtProp))
plotbackend.draw_if_interactive()
return h
def epcolor(*args, **kwds):
'''
Pseudocolor (checkerboard) plot with mid-bin positioning.
h = epcolor(x,y,data)
[x,y]= the axes corresponding to the data-positions. Vectors or
matrices. If omitted, giving only data-matrix as inargument, the
matrix-indices are used as axes.
data = data-matrix
EPCOLOR make a checkerboard plot where the data-point-positions are in
the middle of the bins instead of in the corners, and the last column
and row of data are used.
Example:
>>> import wafo.demos as wd
>>> import wafo.graphutil as wg
>>> x, y, z = wd.peaks(n=20)
>>> h = wg.epcolor(x,y,z)
See also
--------
pylab.pcolor
'''
axis = kwds.pop('axis',None)
if axis is None:
axis = plotbackend.gca()
midbin = kwds.pop('midbin', True)
if not midbin:
ret = axis.pcolor(*args,**kwds)
plotbackend.draw_if_interactive()
return ret
def _parse_data(*args, **kwds):
nargin = len(args)
data = np.atleast_2d(args[-1]).copy()
M, N = data.shape
if nargin==1:
if nargin == 1:
x = np.arange(N)
y = np.arange(M)
elif nargin==3:
elif nargin == 3:
x, y = np.atleast_1d(*args[:-1])
if min(x.shape)!=1:
if min(x.shape) != 1:
x = x[0]
if min(y.shape)!=1:
y = y[:,0]
if min(y.shape) != 1:
y = y[:, 0]
else:
raise ValueError('pcolor takes 3 or 1 inarguments! (x,y,data) or (data)')
raise ValueError(
'Requires 3 or 1 in arguments! (x,y,data) or (data)')
if kwds.pop('mid_point', True):
xx = _find_mid_points(x)
yy = _find_mid_points(y)
return xx, yy, data
return x, y, data
xx = _findbins(x)
yy = _findbins(y)
ret = axis.pcolor(xx, yy, data, **kwds)
plotbackend.draw_if_interactive()
return ret
pcolor = plotbackend.pcolor
pcolormesh = plotbackend.pcolormesh
def _findbins(x):
''' Return points half way between all values of X _and_ outside the
def _find_mid_points(x):
''' Return points half way between all values of X and outside the
endpoints. The outer limits have same distance from X's endpoints as
the limits just inside.
'''
dx = np.diff(x) * 0.5
dx = np.hstack((dx, dx[-1]))
return np.hstack((x[0] - dx[0], x + dx))
return x + dx
def test_docstrings():
import doctest
doctest.testmod()
print('Testing docstrings in %s' % __file__)
doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
if __name__ == '__main__':
test_docstrings()

@ -1,9 +1,10 @@
"""
WAFO
====
WAFO is a toolbox Python routines for statistical analysis and simulation of random waves and random loads.
WAFO is freely redistributable software, see WAFO licence, cf. the GNU General Public License (GPL) and
contain tools for:
WAFO is a toolbox Python routines for statistical analysis and simulation of
random waves and random loads.
WAFO is freely redistributable software, see WAFO licence, cf. the
GNU General Public License (GPL) and contain tools for:
Fatigue Analysis
----------------
@ -22,7 +23,8 @@ Statistics
-Kernel density estimation
-Hidden markov models
WAFO consists of several subpackages and classes with short descriptions below.
WAFO consists of several subpackages and classes with short descriptions given
below.
Classes:
TimeSeries - Data analysis of time series. Example: extraction of
@ -35,7 +37,6 @@ Statistics
Ex: common spectra implemented, directional spectra,
bandwidth measures, exact distributions for wave characteristics.
CyclePairs - Cycle counting, discretization, and crossings, calculation of
damage. Simulation of discrete Markov chains, switching Markov
chains, harmonic oscillator. Ex: Rainflow cycles and matrix,

@ -1428,8 +1428,8 @@ def qdemo(f, a, b):
formats = ['%4.0f, ', ] + ['%10.10f, ', ] * 6
formats[-1] = formats[-1].split(',')[0]
data = np.vstack((neval, qt, et, qs, es, qb, eb)).T
print(' ftn Trapezoid Simpson''s Boole''s')
print('evals approx error approx error approx error')
print(' ftn Trapezoid Simpson''s Boole''s') # @IgnorePep8
print('evals approx error approx error approx error') # @IgnorePep8
for k in xrange(kmax):
tmp = data[k].tolist()
@ -1437,8 +1437,8 @@ def qdemo(f, a, b):
# display results
data = np.vstack((neval, qc, ec, qc2, ec2, qg, eg)).T
print(' ftn Clenshaw Chebychev Gauss-L')
print('evals approx error approx error approx error')
print(' ftn Clenshaw Chebychev Gauss-L') # @IgnorePep8
print('evals approx error approx error approx error') # @IgnorePep8
for k in xrange(kmax):
tmp = data[k].tolist()
print(''.join(fi % t for fi, t in zip(formats, tmp)))
@ -1447,7 +1447,7 @@ def qdemo(f, a, b):
plt.xlabel('number of function evaluations')
plt.ylabel('error')
plt.legend(
('Trapezoid', 'Simpsons', 'Booles', 'Clenshaw', 'Chebychev', 'Gauss-L'))
('Trapezoid', 'Simpsons', 'Booles', 'Clenshaw', 'Chebychev', 'Gauss-L')) # @IgnorePep8
# ec3'

@ -12,9 +12,9 @@
from __future__ import division
import numpy as np
import scipy.signal
import scipy.special as spec
import scipy.sparse as sp
#import scipy.special as spec
import scipy.sparse.linalg # @UnusedImport
import scipy.sparse as sparse
from numpy.ma.core import ones, zeros, prod, sin
from numpy import diff, pi, inf # @UnresolvedImport
from numpy.lib.shape_base import vstack
@ -546,7 +546,7 @@ class SmoothSpline(PPform):
else:
dx1 = 1. / dx
D = sp.spdiags(var * ones(n), 0, n, n) # The variance
D = sparse.spdiags(var * ones(n), 0, n, n) # The variance
u, p = self._compute_u(p, D, dydx, dx, dx1, n)
dx1.shape = (n - 1, -1)
@ -590,10 +590,10 @@ class SmoothSpline(PPform):
def _compute_u(self, p, D, dydx, dx, dx1, n):
if p is None or p != 0:
data = [dx[1:n - 1], 2 * (dx[:n - 2] + dx[1:n - 1]), dx[:n - 2]]
R = sp.spdiags(data, [-1, 0, 1], n - 2, n - 2)
R = sparse.spdiags(data, [-1, 0, 1], n - 2, n - 2)
if p is None or p < 1:
Q = sp.spdiags(
Q = sparse.spdiags(
[dx1[:n - 2], -(dx1[:n - 2] + dx1[1:n - 1]), dx1[1:n - 1]],
[0, -1, -2], n, n - 2)
QDQ = (Q.T * D * Q)
@ -612,8 +612,8 @@ class SmoothSpline(PPform):
# Make sure it uses symmetric matrix solver
ddydx = diff(dydx, axis=0)
sp.linalg.use_solver(useUmfpack=True)
u = 2 * sp.linalg.spsolve((QQ + QQ.T), ddydx)
#sp.linalg.use_solver(useUmfpack=True)
u = 2 * sparse.linalg.spsolve((QQ + QQ.T), ddydx) # @UndefinedVariable
return u.reshape(n - 2, -1), p
@ -923,7 +923,7 @@ class StinemanInterp(object):
'''
def __init__(self, x, y, yp=None, method='parabola', monotone=False):
if yp is None:
yp = slopes(x, y, method, monotone)
yp = slopes(x, y, method, monotone=monotone)
self.x = np.asarray(x, np.float_)
self.y = np.asarray(y, np.float_)
self.yp = np.asarray(yp, np.float_)
@ -1058,7 +1058,8 @@ class Pchip(PiecewisePolynomial):
>>> h=plt.xlabel("X")
>>> h=plt.ylabel("Y")
>>> h=plt.title("Comparing pypchip() vs. Scipy interp1d() vs. non-monotonic CHS")
>>> txt = "Comparing pypchip() vs. Scipy interp1d() vs. non-monotonic CHS"
>>> h=plt.title(txt)
>>> legends = ["Data", "pypchip()", "interp1d","CHS", 'SI']
>>> h=plt.legend(legends, loc="upper left")
>>> plt.show()
@ -1210,10 +1211,10 @@ def test_func():
_tck1, _u = interpolate.splprep([t, y], s=0) # @UndefinedVariable
tck2 = interpolate.splrep(t, y, s=len(t), task=0) # @UndefinedVariable
# interpolate.spl
tck = interpolate.splmake(t, y, order=3, kind='smoothest', conds=None) # @UndefinedVariable
tck = interpolate.splmake(t, y, order=3, kind='smoothest', conds=None)
self = interpolate.ppform.fromspline(*tck2) # @UndefinedVariable
plt.plot(t, self(t))
plt.show()
plt.show('hold')
pass
@ -1238,12 +1239,13 @@ def test_pp():
def test_docstrings():
import doctest
doctest.testmod()
print('Testing docstrings in %s' % __file__)
doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
if __name__ == '__main__':
test_func()
#test_func()
# test_doctstrings()
# test_smoothing_spline()
# compare_methods()
#demo_monoticity()
#compare_methods()
demo_monoticity()

@ -21,7 +21,7 @@ from scipy.ndimage.morphology import distance_transform_edt
from numpy import pi, sqrt, atleast_2d, exp, newaxis # @UnresolvedImport
from wafo.misc import meshgrid, nextpow2, tranproc # , trangood
from wafo.wafodata import PlotData
from wafo.containers import PlotData
from wafo.dctpack import dct, dctn, idctn
from wafo.plotbackend import plotbackend as plt
try:
@ -3984,7 +3984,8 @@ def kreg_demo3(x, y, fun1, hs=None, fun='hisj', plotlog=False):
eerr = np.abs((yiii - fiii)).std() + 0.5 * (df[:-1] * df[1:] < 0).sum() / n
err = (fiii - fit).std()
f = kreg(
xiii, output='plotobj', title='%s err=%1.3f,eerr=%1.3f, n=%d, hs=%1.3f, hs1=%1.3f, hs2=%1.3f' %
xiii, output='plotobj',
title='%s err=%1.3f,eerr=%1.3f, n=%d, hs=%1.3f, hs1=%1.3f, hs2=%1.3f' %
(fun, err, eerr, n, hs, hs1, hs2), plotflag=1)
#yi[yi==0] = 1.0/(c[c!=0].min()+4)
@ -4051,8 +4052,8 @@ def kreg_demo3(x, y, fun1, hs=None, fun='hisj', plotlog=False):
# Wilson score
den = 1 + (z0 ** 2. / ciii)
xc = (pi1 + (z0 ** 2) / (2 * ciii)) / den
halfwidth = (
z0 * sqrt((pi1 * (1 - pi1) / ciii) + (z0 ** 2 / (4 * (ciii ** 2))))) / den
halfwidth = (z0 * sqrt((pi1 * (1 - pi1) / ciii) +
(z0 ** 2 / (4 * (ciii ** 2))))) / den
plo = (xc - halfwidth).clip(min=0) # wilson score
pup = (xc + halfwidth).clip(max=1.0) # wilson score
# pup = (pi + z0*np.sqrt(pi*(1-pi)/ciii)).clip(min=0,max=1) # dont use
@ -4061,14 +4062,18 @@ def kreg_demo3(x, y, fun1, hs=None, fun='hisj', plotlog=False):
#mi = kreg.eval_grid(x)
#sigma = (stineman_interp(x, xiii, pup)-stineman_interp(x, xiii, plo))/4
#aic = np.abs((y-mi)/sigma).std()+ 0.5*(df[:-1]*df[1:]<0).sum()/n
#aic = np.abs((yiii-fiii)/(pup-plo)).std()+ 0.5*(df[:-1]*df[1:]<0).sum() + ((yiii-pup).clip(min=0)-(yiii-plo).clip(max=0)).sum()
#aic = np.abs((yiii-fiii)/(pup-plo)).std() + \
# 0.5*(df[:-1]*df[1:]<0).sum() + \
# ((yiii-pup).clip(min=0)-(yiii-plo).clip(max=0)).sum()
k = (df[:-1] * df[1:] < 0).sum() # numpeaks
sigmai = (pup - plo)
aic = (((yiii - fiii) / sigmai) ** 2).sum() + 2 * k * (k + 1) / np.maximum(ni - k + 1, 1) + \
aic = (((yiii - fiii) / sigmai) ** 2).sum() + \
2 * k * (k + 1) / np.maximum(ni - k + 1, 1) + \
np.abs((yiii - pup).clip(min=0) - (yiii - plo).clip(max=0)).sum()
#aic = (((yiii-fiii)/sigmai)**2).sum()+ 2*k*(k+1)/(ni-k+1) + np.abs((yiii-pup).clip(min=0)-(yiii-plo).clip(max=0)).sum()
#aic = (((yiii-fiii)/sigmai)**2).sum()+ 2*k*(k+1)/(ni-k+1) + \
# np.abs((yiii-pup).clip(min=0)-(yiii-plo).clip(max=0)).sum()
#aic = averr + ((yiii-pup).clip(min=0)-(yiii-plo).clip(max=0)).sum()
@ -4140,14 +4145,16 @@ def kreg_demo4(x, y, hs, hopt, alpha=0.05):
yi = np.where(c == 0, 0, c0 / c)
f.children = [PlotData(
[plo, pup], xiii, plotmethod='fill_between', plot_kwds=dict(alpha=0.2, color='r')),
[plo, pup], xiii, plotmethod='fill_between',
plot_kwds=dict(alpha=0.2, color='r')),
PlotData(yi, xi, plotmethod='scatter', plot_kwds=dict(color='r', s=5))]
yiii = interpolate.interp1d(xi, yi)(xiii)
df = np.diff(fiii)
k = (df[:-1] * df[1:] < 0).sum() # numpeaks
sigmai = (pup - plo)
aicc = (((yiii - fiii) / sigmai) ** 2).sum() + 2 * k * (k + 1) / np.maximum(ni - k + 1, 1) + \
aicc = (((yiii - fiii) / sigmai) ** 2).sum() + \
2 * k * (k + 1) / np.maximum(ni - k + 1, 1) + \
np.abs((yiii - pup).clip(min=0) - (yiii - plo).clip(max=0)).sum()
f.aicc = aicc
@ -4168,7 +4175,7 @@ def check_kreg_demo3():
for fun in ['hste', ]:
#@UnusedVariable
hsmax, hs1, hs2 = _get_regression_smooting(x, y, fun=fun)
hsmax, _hs1, _hs2 = _get_regression_smooting(x, y, fun=fun)
for hi in np.linspace(hsmax * 0.25, hsmax, 9):
plt.figure(k)
k += 1
@ -4197,7 +4204,7 @@ def check_kreg_demo4():
hopt = sqrt(hopt1 * hopt2)
#hopt = _get_regression_smooting(x,y,fun='hos')[0]
# , 'hisj', 'hns', 'hstt' @UnusedVariable
for j, fun in enumerate(['hste']):
for _j, fun in enumerate(['hste']):
hsmax, _hs1, _hs2 = _get_regression_smooting(x, y, fun=fun)
fmax = kreg_demo4(x, y, hsmax + 0.1, hopt)
@ -4320,10 +4327,12 @@ def empirical_bin_prb(x, y, hopt, color='r'):
else:
c0 = np.zeros(xi.shape)
yi = np.where(c == 0, 0, c0 / c)
return PlotData(yi, xi, plotmethod='scatter', plot_kwds=dict(color=color, s=5))
return PlotData(yi, xi, plotmethod='scatter',
plot_kwds=dict(color=color, s=5))
def smoothed_bin_prb(x, y, hs, hopt, alpha=0.05, color='r', label='', bin_prb=None):
def smoothed_bin_prb(x, y, hs, hopt, alpha=0.05, color='r', label='',
bin_prb=None):
'''
Parameters
----------
@ -4379,14 +4388,16 @@ def smoothed_bin_prb(x, y, hs, hopt, alpha=0.05, color='r', label='', bin_prb=No
if label:
f.plot_kwds['label'] = label
f.children = [PlotData(
[plo, pup], xiii, plotmethod='fill_between', plot_kwds=dict(alpha=0.2, color=color)),
[plo, pup], xiii, plotmethod='fill_between',
plot_kwds=dict(alpha=0.2, color=color)),
bin_prb]
yiii = interpolate.interp1d(xi, yi)(xiii)
df = np.diff(fiii)
k = (df[:-1] * df[1:] < 0).sum() # numpeaks
sigmai = (pup - plo)
aicc = (((yiii - fiii) / sigmai) ** 2).sum() + 2 * k * (k + 1) / np.maximum(ni - k + 1, 1) + \
aicc = (((yiii - fiii) / sigmai) ** 2).sum() + \
2 * k * (k + 1) / np.maximum(ni - k + 1, 1) + \
np.abs((yiii - pup).clip(min=0) - (yiii - plo).clip(max=0)).sum()
f.aicc = aicc
@ -4408,17 +4419,15 @@ def regressionbin(x, y, alpha=0.05, color='r', label=''):
y : arraylike
of 0 and 1
'''
# @UnusedVariable
hopt1, h1, h2 = _get_regression_smooting(x, y, fun='hos')
# @UnusedVariable
hopt2, h1, h2 = _get_regression_smooting(x, y, fun='hste')
hopt1, _h1, _h2 = _get_regression_smooting(x, y, fun='hos')
hopt2, _h1, _h2 = _get_regression_smooting(x, y, fun='hste')
hopt = sqrt(hopt1 * hopt2)
fbest = smoothed_bin_prb(x, y, hopt2 + 0.1, hopt, alpha, color, label)
bin_prb = fbest.children[-1]
for fun in ['hste']: # , 'hisj', 'hns', 'hstt'
#@UnusedVariable
hsmax, hs1, hs2 = _get_regression_smooting(x, y, fun=fun)
hsmax, _hs1, _hs2 = _get_regression_smooting(x, y, fun=fun)
for hi in np.linspace(hsmax * 0.1, hsmax, 55):
f = smoothed_bin_prb(x, y, hi, hopt, alpha, color, label, bin_prb)
if f.aicc <= fbest.aicc:
@ -4479,8 +4488,8 @@ def kde_gauss_demo(n=50):
print(fmax / f2.data.max())
format_ = ''.join(('%g, ') * d)
format_ = 'hs0=%s hs1=%s hs2=%s' % (format_, format_, format_)
print(
format_ % tuple(kde0.hs.tolist() + kde1.tkde.hs.tolist() + kde2.hs.tolist()))
print(format_ % tuple(kde0.hs.tolist() +
kde1.tkde.hs.tolist() + kde2.hs.tolist()))
print('inc0 = %d, inc1 = %d, inc2 = %d' % (kde0.inc, kde1.inc, kde2.inc))

@ -1,136 +0,0 @@
import numpy as np
def meshgrid(*xi, **kwargs):
"""
Return coordinate matrices from one or more coordinate vectors.
Make N-D coordinate arrays for vectorized evaluations of
N-D scalar/vector fields over N-D grids, given
one-dimensional coordinate arrays x1, x2,..., xn.
Parameters
----------
x1, x2,..., xn : array_like
1-D arrays representing the coordinates of a grid.
indexing : 'xy' or 'ij' (optional)
cartesian ('xy', default) or matrix ('ij') indexing of output
sparse : True or False (default) (optional)
If True a sparse grid is returned in order to conserve memory.
copy : True (default) or False (optional)
If False a view into the original arrays are returned in order to
conserve memory. Please note that sparse=False, copy=False will likely
return non-contiguous arrays. Furthermore, more than one element of a
broadcasted array may refer to a single memory location. If you
need to write to the arrays, make copies first.
Returns
-------
X1, X2,..., XN : ndarray
For vectors `x1`, `x2`,..., 'xn' with lengths ``Ni=len(xi)`` ,
return ``(N1, N2, N3,...Nn)`` shaped arrays if indexing='ij'
or ``(N2, N1, N3,...Nn)`` shaped arrays if indexing='xy'
with the elements of `xi` repeated to fill the matrix along
the first dimension for `x1`, the second for `x2` and so on.
Notes
-----
This function supports both indexing conventions through the indexing
keyword argument. Giving the string 'ij' returns a meshgrid with matrix
indexing, while 'xy' returns a meshgrid with Cartesian indexing. The
difference is illustrated by the following code snippet:
xv, yv = meshgrid(x, y, sparse=False, indexing='ij')
for i in range(nx):
for j in range(ny):
# treat xv[i,j], yv[i,j]
xv, yv = meshgrid(x, y, sparse=False, indexing='xy')
for i in range(nx):
for j in range(ny):
# treat xv[j,i], yv[j,i]
See Also
--------
index_tricks.mgrid : Construct a multi-dimensional "meshgrid"
using indexing notation.
index_tricks.ogrid : Construct an open multi-dimensional "meshgrid"
using indexing notation.
Examples
--------
>>> nx, ny = (3, 2)
>>> x = np.linspace(0, 1, nx)
>>> y = np.linspace(0, 1, ny)
>>> xv, yv = meshgrid(x, y)
>>> xv
array([[ 0. , 0.5, 1. ],
[ 0. , 0.5, 1. ]])
>>> yv
array([[ 0., 0., 0.],
[ 1., 1., 1.]])
>>> xv, yv = meshgrid(x, y, sparse=True) # make sparse output arrays
>>> xv
array([[ 0. , 0.5, 1. ]])
>>> yv
array([[ 0.],
[ 1.]])
`meshgrid` is very useful to evaluate functions on a grid.
>>> x = np.arange(-5, 5, 0.1)
>>> y = np.arange(-5, 5, 0.1)
>>> xx, yy = meshgrid(x, y, sparse=True)
>>> z = np.sin(xx**2+yy**2)/(xx**2+yy**2)
>>> import matplotlib.pyplot as plt
>>> h = plt.contourf(x,y,z)
"""
copy_ = kwargs.get('copy', True)
args = np.atleast_1d(*xi)
ndim = len(args)
if not isinstance(args, list) or ndim < 2:
raise TypeError(
'meshgrid() takes 2 or more arguments (%d given)' % int(ndim > 0))
sparse = kwargs.get('sparse', False)
indexing = kwargs.get('indexing', 'xy')
s0 = (1,) * ndim
output = [x.reshape(s0[:i] + (-1,) + s0[i + 1::])
for i, x in enumerate(args)]
shape = [x.size for x in output]
if indexing == 'xy':
# switch first and second axis
output[0].shape = (1, -1) + (1,) * (ndim - 2)
output[1].shape = (-1, 1) + (1,) * (ndim - 2)
shape[0], shape[1] = shape[1], shape[0]
if sparse:
if copy_:
return [x.copy() for x in output]
else:
return output
else:
# Return the full N-D matrix (not only the 1-D vector)
if copy_:
mult_fact = np.ones(shape, dtype=int)
return [x * mult_fact for x in output]
else:
return np.broadcast_arrays(*output)
def ndgrid(*args, **kwargs):
"""
Same as calling meshgrid with indexing='ij' (see meshgrid for
documentation).
"""
kwargs['indexing'] = 'ij'
return meshgrid(*args, **kwargs)
if __name__ == '__main__':
import doctest
doctest.testmod()

File diff suppressed because it is too large Load Diff

@ -2,6 +2,7 @@ from operator import itemgetter as _itemgetter
from keyword import iskeyword as _iskeyword
import sys as _sys
def namedtuple(typename, field_names, verbose=False):
"""Returns a new subclass of tuple with named fields.
@ -27,30 +28,39 @@ def namedtuple(typename, field_names, verbose=False):
"""
# Parse and validate the field names. Validation serves two purposes,
# generating informative error messages and preventing template injection attacks.
# generating informative error messages and preventing template injection
# attacks.
if isinstance(field_names, basestring):
field_names = field_names.replace(',', ' ').split() # names separated by whitespace and/or commas
# names separated by whitespace and/or commas
field_names = field_names.replace(',', ' ').split()
field_names = tuple(field_names)
for name in (typename,) + field_names:
if not min(c.isalnum() or c=='_' for c in name):
raise ValueError('Type names and field names can only contain alphanumeric characters and underscores: %r' % name)
if not min(c.isalnum() or c == '_' for c in name):
raise ValueError(
'Type names and field names can only contain alphanumeric ' +
'characters and underscores: %r' % name)
if _iskeyword(name):
raise ValueError('Type names and field names cannot be a keyword: %r' % name)
raise ValueError(
'Type names and field names cannot be a keyword: %r' % name)
if name[0].isdigit():
raise ValueError('Type names and field names cannot start with a number: %r' % name)
raise ValueError('Type names and field names cannot start ' +
'with a number: %r' % name)
seen_names = set()
for name in field_names:
if name.startswith('_'):
raise ValueError('Field names cannot start with an underscore: %r' % name)
raise ValueError(
'Field names cannot start with an underscore: %r' % name)
if name in seen_names:
raise ValueError('Encountered duplicate field name: %r' % name)
seen_names.add(name)
# Create and fill-in the class template
numfields = len(field_names)
argtxt = repr(field_names).replace("'", "")[1:-1] # tuple repr without parens or quotes
# tuple repr without parens or quotes
argtxt = repr(field_names).replace("'", "")[1:-1]
reprtxt = ', '.join('%s=%%r' % name for name in field_names)
dicttxt = ', '.join('%r: t[%d]' % (name, pos) for pos, name in enumerate(field_names))
dicttxt = ', '.join('%r: t[%d]' % (name, pos)
for pos, name in enumerate(field_names))
template = '''class %(typename)s(tuple):
'%(typename)s(%(argtxt)s)' \n
__slots__ = () \n
@ -88,19 +98,15 @@ def namedtuple(typename, field_names, verbose=False):
raise SyntaxError(e.message + ':\n' + template)
result = namespace[typename]
# For pickling to work, the __module__ variable needs to be set to the frame
# where the named tuple is created. Bypass this step in enviroments where
# sys._getframe is not defined (Jython for example).
# For pickling to work, the __module__ variable needs to be set to the
# frame where the named tuple is created. Bypass this step in enviroments
# where sys._getframe is not defined (Jython for example).
if hasattr(_sys, '_getframe'):
result.__module__ = _sys._getframe(1).f_globals['__name__']
return result
if __name__ == '__main__':
# verify that instances can be pickled
from cPickle import loads, dumps
@ -110,18 +116,24 @@ if __name__ == '__main__':
# test and demonstrate ability to override methods
class Point(namedtuple('Point', 'x y')):
@property
def hypot(self):
return (self.x ** 2 + self.y ** 2) ** 0.5
def __str__(self):
return 'Point: x=%6.3f y=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot)
return 'Point: x=%6.3f y=%6.3f hypot=%6.3f' % (self.x, self.y,
self.hypot)
for p in Point(3,4), Point(14,5), Point(9./7,6):
for p in Point(3, 4), Point(14, 5), Point(9. / 7, 6):
print p
class Point(namedtuple('Point', 'x y')):
'Point class with optimized _make() and _replace() without error-checking'
'''Point class with optimized _make() and _replace()
without error-checking
'''
_make = classmethod(tuple.__new__)
def _replace(self, _map=map, **kwds):
return self._make(_map(kwds.get, ('x', 'y'), self))

File diff suppressed because it is too large Load Diff

@ -7,7 +7,7 @@ if False:
try:
from scitools import easyviz as plotbackend
if verbose:
print('wafo.wafodata: plotbackend is set to scitools.easyviz')
print('wafo: plotbackend is set to scitools.easyviz')
except:
warnings.warn('wafo: Unable to load scitools.easyviz as plotbackend')
plotbackend = None
@ -16,7 +16,7 @@ else:
from matplotlib import pyplot as plotbackend
plotbackend.interactive(True)
if verbose:
print('wafo.wafodata: plotbackend is set to matplotlib.pyplot')
print('wafo: plotbackend is set to matplotlib.pyplot')
except:
warnings.warn('wafo: Unable to load matplotlib.pyplot as plotbackend')
plotbackend = None

File diff suppressed because it is too large Load Diff

@ -9,28 +9,33 @@ Created on 15. des. 2009
#from win32com.client.selecttlb import EnumTlbs
#typelib_mso = None
#typelib_msppt = None
#for typelib in EnumTlbs():
# for typelib in EnumTlbs():
# d = typelib.desc.split(' ')
# if d[0] == 'Microsoft' and d[1] == 'Office' and d[3] == 'Object' and d[4] == 'Library':
# if d[0] == 'Microsoft' and d[1] == 'Office' and d[3] == 'Object' \
# and d[4] == 'Library':
# typelib_mso = typelib
# if d[0] == 'Microsoft' and d[1] == 'PowerPoint' and d[3] == 'Object' and d[4] == 'Library':
# if d[0] == 'Microsoft' and d[1] == 'PowerPoint' and d[3] == 'Object' \
# and d[4] == 'Library':
# typelib_msppt = typelib
#if hasattr(sys, 'frozen'): # If we're an .exe file
# if hasattr(sys, 'frozen'): # If we're an .exe file
# win32com.__gen_path__ = os.path.dirname(sys.executable)
## win32com.__gen_path__ = os.environ['TEMP']
#if win32com.client.gencache.is_readonly:
# if win32com.client.gencache.is_readonly:
# win32com.client.gencache.is_readonly = False
# win32com.client.gencache.Rebuild()
#MSPPT = win32com.client.gencache.EnsureModule(typelib_msppt.clsid, typelib_msppt.lcid,
# int(typelib_msppt.major), int(typelib_msppt.minor))
#MSO = win32com.client.gencache.EnsureModule(typelib_mso.clsid, typelib_mso.lcid,
# MSPPT = win32com.client.gencache.EnsureModule(typelib_msppt.clsid,
# typelib_msppt.lcid,
# int(typelib_msppt.major),
# int(typelib_msppt.minor))
# MSO = win32com.client.gencache.EnsureModule(typelib_mso.clsid,
# typelib_mso.lcid,
# int(typelib_mso.major), int(typelib_mso.minor))
import os
import warnings
import win32com.client
import MSO
import MSPPT
from PIL import Image #@UnresolvedImport
from PIL import Image # @UnresolvedImport
g = globals()
for c in dir(MSO.constants):
@ -38,7 +43,9 @@ for c in dir(MSO.constants):
for c in dir(MSPPT.constants):
g[c] = getattr(MSPPT.constants, c)
class Powerpoint(object):
def __init__(self, file_name=''):
self.application = win32com.client.Dispatch("Powerpoint.Application")
@ -52,9 +59,9 @@ class Powerpoint(object):
# default picture width and height
self.default_width = 500
self.default_height = 400
self.title_font = 'Arial' #'Boopee'
self.title_font = 'Arial' # 'Boopee'
self.title_size = 36
self.text_font = 'Arial' #'Boopee'
self.text_font = 'Arial' # 'Boopee'
self.text_size = 20
self.footer = ''
@ -71,43 +78,49 @@ class Powerpoint(object):
SMHF = self.presentation.SlideMaster.HeadersFooters
SMHF.Footer.Text = self.footer
SMHF.Footer.Visible = True
SMHF.SlideNumber.Visible= True
SMHF.SlideNumber.Visible = True
NMHF = self.presentation.NotesMaster.HeadersFooters
NMHF.Footer.Text = self.footer
NMHF.SlideNumber.Visible= True
NMHF.SlideNumber.Visible = True
for slide in self.presentation.Slides:
shapes = slide.Shapes
for shape in shapes:
if shape.Name=='Footer':
if shape.Name == 'Footer':
footer = shape
break
else:
footer = shapes.AddTextbox(msoTextOrientationHorizontal, Left=0, Top=510, Width=720, Height=28.875) #@UndefinedVariable
footer = shapes.AddTextbox(
msoTextOrientationHorizontal, # @UndefinedVariable
Left=0, Top=510, Width=720, Height=28.875)
footer.Name = 'Footer'
footer.TextFrame.TextRange.Text = self.footer
def add_title_slide(self, title, subtitle=''):
self.num_slides +=1
slide = self.presentation.Slides.Add(self.num_slides, MSPPT.constants.ppLayoutTitle)
self.num_slides += 1
slide = self.presentation.Slides.Add(
self.num_slides, MSPPT.constants.ppLayoutTitle)
unused_title_id, unused_textbox_id = 1, 2
for id_, title1 in enumerate([title, subtitle]):
titlerange = slide.Shapes(id_+1).TextFrame.TextRange
titlerange = slide.Shapes(id_ + 1).TextFrame.TextRange
titlerange.Text = title1
titlerange.Font.Name = self.title_font
titlerange.Font.Size = self.title_size-id_*12 if self.title_size>22 else self.title_size
titlerange.Font.Size = self.title_size - id_ * \
12 if self.title_size > 22 else self.title_size
def add_slide(self, title='', texts='', notes='', image_file='',
maxlevel=None, left=220, width=-1, height=-1):
self.num_slides +=1
slide = self.presentation.Slides.Add(self.num_slides, MSPPT.constants.ppLayoutText)
self.num_slides += 1
slide = self.presentation.Slides.Add(
self.num_slides, MSPPT.constants.ppLayoutText)
self.add2slide(slide, title, texts, notes, image_file, maxlevel, left, width, height)
self.add2slide(slide, title, texts, notes, image_file, maxlevel, left,
width, height)
return slide
def add2slide(self, slide, title='', texts='', notes='', image_file='',
maxlevel=None, left=220, width=-1, height=-1, keep_aspect=True):
maxlevel=None, left=220, width=-1, height=-1,
keep_aspect=True):
title_id, textbox_id = 1, 2
if title:
titlerange = slide.Shapes(title_id).TextFrame.TextRange
@ -123,26 +136,26 @@ class Powerpoint(object):
if keep_aspect:
im = Image.open(image_file)
t_w, t_h = im.size
if height<=0 and width<=0:
if t_w*self.default_height < t_h*self.default_width:
if height <= 0 and width <= 0:
if t_w * self.default_height < t_h * self.default_width:
height = self.default_height
else:
width = self.default_width
if height<=0 and width:
if height <= 0 and width:
height = t_h * width / t_w
elif height and width <=0:
elif height and width <= 0:
width = t_w * height / t_h
slide.Shapes.AddPicture(FileName=image_file, LinkToFile=False,
SaveWithDocument=True,
Left=left, Top=110,
Width=width, Height=height) #400)
Width=width, Height=height) # 400)
if notes != '' and notes != ['']:
notespage = slide.NotesPage #.Shapes(2).TextFrame.TextRange
notespage = slide.NotesPage # .Shapes(2).TextFrame.TextRange
self._add_text(notespage, 2, notes)
return slide
def _add_text(self, page, id, txt, maxlevel=None): #@ReservedAssignment
def _add_text(self, page, id, txt, maxlevel=None): # @ReservedAssignment
page.Shapes(id).TextFrame.TextRange.Font.Name = self.text_font
if isinstance(txt, dict):
@ -155,34 +168,37 @@ class Powerpoint(object):
page.Shapes(id).TextFrame.TextRange.Font.Size = self.text_size
def _add_text_from_dict(self, page, id, txt_dict, level, maxlevel=None): #@ReservedAssignment
if maxlevel is None or level<=maxlevel:
def _add_text_from_dict(self, page, id, txt_dict, # @ReservedAssignment
level, maxlevel=None):
if maxlevel is None or level <= maxlevel:
for name, subdict in txt_dict.iteritems():
tr = page.Shapes(id).TextFrame.TextRange.InsertAfter(name)
unused_temp = page.Shapes(id).TextFrame.TextRange.InsertAfter('\r')
unused_temp = page.Shapes(
id).TextFrame.TextRange.InsertAfter('\r')
tr.IndentLevel = level
self._add_text_from_dict(page, id, subdict, min(level+1,5), maxlevel)
self._add_text_from_dict(
page, id, subdict, min(level + 1, 5), maxlevel)
def _add_text_from_list(self, page, id, txt_list, maxlevel=None): #@ReservedAssignment
def _add_text_from_list(self, page, id, # @ReservedAssignment
txt_list, maxlevel=None):
for txt in txt_list:
level = 1
while isinstance(txt, (list, tuple)):
txt = txt[0]
level += 1
if maxlevel is None or level<=maxlevel:
if maxlevel is None or level <= maxlevel:
tr = page.Shapes(id).TextFrame.TextRange.InsertAfter(txt)
unused_temp = page.Shapes(id).TextFrame.TextRange.InsertAfter('\r')
unused_temp = page.Shapes(
id).TextFrame.TextRange.InsertAfter('\r')
tr.IndentLevel = level
def save(self, fullfile=''):
if fullfile:
self.presentation.SaveAs(FileName=fullfile)
else:
self.presentation.Save()
def quit(self): #@ReservedAssignment
def quit(self): # @ReservedAssignment
if self._visible:
self.presentation.Close()
else:
@ -192,43 +208,44 @@ class Powerpoint(object):
if not self._visible:
self.application.Quit()
def test_powerpoint():
# Make powerpoint
ppt = Powerpoint()
#time.
ppt.footer='This is the footer'
# time.
ppt.footer = 'This is the footer'
ppt.add_title_slide('Title', 'Per A.')
ppt.add_slide(title='alsfkasldk', texts='asdflaf', notes='asdfas')
ppt.set_footer()
def make_ppt():
application = win32com.client.Dispatch("Powerpoint.Application")
application.Visible = True
presentation = application.Presentations.Add()
slide1 = presentation.Slides.Add(1, MSPPT.constants.ppLayoutText)
# title = slide1.Shapes.AddTextBox(Type=msoTextOrientationHorizontal,Left=50, Top=10, Width=620, Height=70)
# title = slide1.Shapes.AddTextBox(Type=msoTextOrientationHorizontal,
# Left=50, Top=10, Width=620, Height=70)
# title.TextFrame.TextRange.Text = 'Overskrift'
title_id, textbox_id = 1,2
title_id, textbox_id = 1, 2
slide1.Shapes(title_id).TextFrame.TextRange.Text = 'Overskrift'
#slide1.Shapes(title_id).TextFrame.Width = 190
slide1.Shapes(textbox_id).TextFrame.TextRange.InsertAfter('Test')
unused_tr = slide1.Shapes(textbox_id).TextFrame.TextRange.InsertAfter('\r')
slide1.Shapes(textbox_id).TextFrame.TextRange.IndentLevel = 1
tr = slide1.Shapes(textbox_id).TextFrame.TextRange.InsertAfter('tests')
unused_tr0 = slide1.Shapes(textbox_id).TextFrame.TextRange.InsertAfter('\r')
tr.IndentLevel=2
unused_tr0 = slide1.Shapes(
textbox_id).TextFrame.TextRange.InsertAfter('\r')
tr.IndentLevel = 2
tr1 = slide1.Shapes(textbox_id).TextFrame.TextRange.InsertAfter('test3')
tr1.IndentLevel=3
tr1.IndentLevel = 3
#slide1.Shapes(textbox_id).TextFrame.TextRange.Text = 'Test \r test2'
# textbox = slide1.Shapes.AddTextBox(Type=msoTextOrientationHorizontal,Left=30, Top=100, Width=190, Height=400)
# textbox = slide1.Shapes.AddTextBox(Type=msoTextOrientationHorizontal,
# Left=30, Top=100, Width=190, Height=400)
# textbox.TextFrame.TextRange.Text = 'Test \r test2'
#picbox = slide1.Shapes(picb_id)
@ -240,14 +257,12 @@ def make_ppt():
slide1.NotesPage.Shapes(2).TextFrame.TextRange.Text = 'test'
# for shape in slide1.Shapes:
# shape.TextFrame.TextRange.Text = 'Test \r test2'
#slide1.Shapes.Titles.TextFrames.TestRange.Text
# slide1.Shapes.Titles.TextFrames.TestRange.Text
# shape = slide1.Shapes.AddShape(msoShapeRectangle, 300, 100, 400, 400)
# shape.TextFrame.TextRange.Text = 'Test \n test2'
# shape.TextFrame.TextRange.Font.Size = 12
#
# app = wx.PySimpleApp()
# dialog = wx.FileDialog(None, 'Choose image file', defaultDir=os.getcwd(),
@ -261,8 +276,8 @@ def make_ppt():
# SaveWithDocument=True,
# Left=100, Top=100, Width=200, Height=200)
# dialog.Destroy()
#presentation.Save()
#application.Quit()
# presentation.Save()
# application.Quit()
def rename_ppt():
root = r'C:/pab/tsm_opeval/analysis_tsmps_aco_v2008b/plots'
# root = r'C:/pab/tsm_opeval/analysis_tsmps_mag_v2008b/plots'
@ -275,12 +290,14 @@ def rename_ppt():
for filename in filenames:
if filename.endswith('.ppt'):
try:
ppt = Powerpoint(os.path.join(root,filename))
ppt = Powerpoint(os.path.join(root, filename))
ppt.footer = prefix + filename
ppt.set_footer()
ppt.save(os.path.join(root, ppt.footer))
except:
warnings.warn('Unable to load %s' % filename)
def load_file_into_ppt():
root = r'C:/pab/tsm_opeval/analysis_tsmps_aco_v2008b/plots'
# root = r'C:/pab/tsm_opeval/analysis_tsmps_mag_v2008b/plots'
@ -293,11 +310,11 @@ def load_file_into_ppt():
for filename in filenames:
if filename.startswith(prefix) and filename.endswith('.ppt'):
try:
unused_ppt = Powerpoint(os.path.join(root,filename))
unused_ppt = Powerpoint(os.path.join(root, filename))
except:
warnings.warn('Unable to load %s' % filename)
if __name__ == '__main__':
#make_ppt()
#test_powerpoint()
#load_file_into_ppt()
# make_ppt()
# test_powerpoint()
# load_file_into_ppt()
rename_ppt()

@ -1,17 +1,20 @@
import numpy as np
#from math import pow
#from numpy import zeros,dot
from numpy import abs, size, convolve, linalg, concatenate #@UnresolvedImport
from numpy import abs, size, convolve, linalg, concatenate # @UnresolvedImport
from scipy.sparse import spdiags
from scipy.sparse.linalg import spsolve, expm
from scipy.signal import medfilt
__all__ = ['calc_coeff', 'smooth', 'smooth_last']
__all__ = ['calc_coeff', 'smooth', 'smooth_last',
'SavitzkyGolay', 'Kalman', 'HodrickPrescott']
def calc_coeff(n, degree, diff_order=0):
""" calculates filter coefficients for symmetric savitzky-golay filter.
see: http://www.nrbook.com/a/bookcpdf/c14-8.pdf
n means that 2*n+1 values contribute to the
smoother.
n means that 2*n+1 values contribute to the smoother.
degree is degree of fitting polynomial
@ -29,6 +32,7 @@ def calc_coeff(n, degree, diff_order=0):
coeff = linalg.pinv(b).A[diff_order]
return coeff
def smooth_last(signal, coeff, k=0):
n = size(coeff - 1) // 2
y = np.squeeze(signal)
@ -41,12 +45,12 @@ def smooth_last(signal, coeff, k=0):
def smooth(signal, coeff, pad=True):
""" applies coefficients calculated by calc_coeff()
to signal """
"""applies coefficients calculated by calc_coeff() to signal."""
n = size(coeff - 1) // 2
y = np.squeeze(signal)
if n == 0:
return y
if pad:
first_vals = y[0] - abs(y[n:0:-1] - y[0])
last_vals = y[-1] + abs(y[-2:-n - 2:-1] - y[-1])
@ -63,8 +67,9 @@ def smooth(signal, coeff, pad=True):
res = convolve(y, coeff)[n:-n]
return res
class SavitzkyGolay(object):
r"""Smooth (and optionally differentiate) data with a Savitzky-Golay filter.
r"""Smooth and optionally differentiate data with a Savitzky-Golay filter.
The Savitzky-Golay filter removes high frequency noise from data.
It has the advantage of preserving the original shape and
@ -79,10 +84,10 @@ class SavitzkyGolay(object):
the order of the polynomial used in the filtering.
Must be less than `window_size` - 1, i.e, less than 2*n.
diff_order : int
the order of the derivative to compute (default = 0 means only smoothing)
order of the derivative to compute (default = 0 means only smoothing)
0 means that filter results in smoothing of function
1 means that filter results in smoothing the first derivative of function.
and so on ...
1 means that filter results in smoothing the first derivative of the
function and so on ...
Notes
-----
@ -96,13 +101,14 @@ class SavitzkyGolay(object):
--------
>>> t = np.linspace(-4, 4, 500)
>>> y = np.exp( -t**2 ) + np.random.normal(0, 0.05, t.shape)
>>> ysg = SavitzkyGolay(n=15, degree=4).smooth(y)
>>> ysg = SavitzkyGolay(n=20, degree=2).smooth(y)
>>> import matplotlib.pyplot as plt
>>> hy = plt.plot(t, y, label='Noisy signal')
>>> h = plt.plot(t, np.exp(-t**2), 'k', lw=1.5, label='Original signal')
>>> h = plt.plot(t, ysg, 'r', label='Filtered signal')
>>> h = plt.legend()
>>> plt.show()
>>> h = plt.plot(t, y, label='Noisy signal')
>>> h1 = plt.plot(t, np.exp(-t**2), 'k', lw=1.5, label='Original signal')
>>> h2 = plt.plot(t, ysg, 'r', label='Filtered signal')
>>> h3 = plt.legend()
>>> h4 = plt.title('Savitzky-Golay')
plt.show()
References
----------
@ -113,6 +119,7 @@ class SavitzkyGolay(object):
W.H. Press, S.A. Teukolsky, W.T. Vetterling, B.P. Flannery
Cambridge University Press ISBN-13: 9780521880688
"""
def __init__(self, n, degree=1, diff_order=0):
self.n = n
self.degree = degree
@ -126,12 +133,15 @@ class SavitzkyGolay(object):
order_range = np.arange(self.degree + 1)
k_range = np.arange(-n, n + 1, dtype=float).reshape(-1, 1)
b = np.mat(k_range ** order_range)
#b = np.mat([[float(k)**i for i in order_range] for k in range(-n,n+1)])
#b =np.mat([[float(k)**i for i in order_range] for k in range(-n,n+1)])
self._coeff = linalg.pinv(b).A[self.diff_order]
def smooth_last(self, signal, k=0):
coeff = self._coeff
n = size(coeff - 1) // 2
y = np.squeeze(signal)
if n == 0:
return y
if y.ndim > 1:
coeff.shape = (-1, 1)
first_vals = y[0] - abs(y[n:0:-1] - y[0])
@ -139,6 +149,8 @@ class SavitzkyGolay(object):
y = concatenate((first_vals, y, last_vals))
return (y[-2 * n - 1 - k:-k] * coeff).sum(axis=0)
def __call__(self, signal):
return self.smooth(signal)
def smooth(self, signal, pad=True):
"""
@ -159,6 +171,8 @@ class SavitzkyGolay(object):
coeff = self._coeff
n = size(coeff - 1) // 2
y = np.squeeze(signal)
if n == 0:
return y
if pad:
first_vals = y[0] - abs(y[n:0:-1] - y[0])
last_vals = y[-1] + abs(y[-2:-n - 2:-1] - y[-1])
@ -175,7 +189,72 @@ class SavitzkyGolay(object):
res = convolve(y, coeff)[n:-n]
return res
class HodrickPrescott(object):
'''Smooth data with a Hodrick-Prescott filter.
The Hodrick-Prescott filter removes high frequency noise from data.
It has the advantage of preserving the original shape and
features of the signal better than other types of filtering
approaches, such as moving averages techniques.
Parameter
---------
w : real scalar
smooting parameter. Larger w means more smoothing. Values usually
in the [100, 20000] interval. As w approach infinity H-P will approach
a line.
Examples
--------
>>> t = np.linspace(-4, 4, 500)
>>> y = np.exp( -t**2 ) + np.random.normal(0, 0.05, t.shape)
>>> ysg = HodrickPrescott(w=10000)(y)
>>> import matplotlib.pyplot as plt
>>> h = plt.plot(t, y, label='Noisy signal')
>>> h1 = plt.plot(t, np.exp(-t**2), 'k', lw=1.5, label='Original signal')
>>> h2 = plt.plot(t, ysg, 'r', label='Filtered signal')
>>> h3 = plt.legend()
>>> h4 = plt.title('Hodrick-Prescott')
>>> plt.show()
References
----------
.. [1] E. T. Whittaker, On a new method of graduation. In proceedings of
the Edinburgh Mathematical association., 1923, 78, pp 88-89.
.. [2] R. Hodrick and E. Prescott, Postwar U.S. business cycles: an
empirical investigation,
Journal of money, credit and banking, 1997, 29 (1), pp 1-16.
.. [3] Kim Hyeongwoo, Hodrick-Prescott filter,
2004, www.auburn.edu/~hzk0001/hpfilter.pdf
'''
def __init__(self, w=100):
self.w = w
def _get_matrix(self, n):
w = self.w
diag_matrix = np.repeat(
np.atleast_2d([w, -4 * w, 6 * w + 1, -4 * w, w]).T, n, axis=1)
A = spdiags(diag_matrix, np.arange(-2, 2 + 1), n, n).tocsr()
A[0, 0] = A[-1, -1] = 1 + w
A[1, 1] = A[-2, -2] = 1 + 5 * w
A[0, 1] = A[1, 0] = A[-2, -1] = A[-1, -2] = -2 * w
return A
def __call__(self, x):
x = np.atleast_1d(x).flatten()
n = len(x)
if n < 4:
return x.copy()
A = self._get_matrix(n)
return spsolve(A, x)
class Kalman(object):
'''
Kalman filter object - updates a system state vector estimate based upon an
observation, using a discrete Kalman filter.
@ -200,8 +279,8 @@ class Kalman(object):
matrix.
USAGE:
filt = Kalman(R, x, P, A, B=0, u=0, Q, H)
x = filt(z)
filt = Kalman(R, x, P, A, B=0, Q, H)
x = filt(z, u=0)
filt is a "system" object containing various fields used as input
and output. The state estimate "x" and its covariance "P" are
@ -241,8 +320,8 @@ class Kalman(object):
information from the new observation). In the output struct,
this is the "a posteriori" state estimate (after the new
measurement information is included).
s.z = observation vector
s.u = input control vector, optional (defaults to zero).
z = observation vector
u = input control vector, optional (defaults to zero).
MATRIX VARIABLES:
@ -285,7 +364,7 @@ class Kalman(object):
>>> r = 0.1**2 # variance of measurement error
>>> b = 0 # no system input
>>> u = 0 # no system input
>>> filt = Kalman(R=r, A=1, Q=q, H=h, B=b, u=u)
>>> filt = Kalman(R=r, A=1, Q=q, H=h, B=b)
# Generate random voltages and watch the filter operate.
>>> n = 50
@ -294,32 +373,34 @@ class Kalman(object):
>>> x = np.zeros(n)
>>> for i, zi in enumerate(z):
... x[i] = filt(zi) # perform a Kalman filter iteration
... x[i] = filt(zi, u) # perform a Kalman filter iteration
>>> import matplotlib.pyplot as plt
>>> hz = plt.plot(z,'r.', label='observations')
>>> hx = plt.plot(x,'b-', label='Kalman output') # a-posteriori state estimates:
# a-posteriori state estimates:
>>> hx = plt.plot(x,'b-', label='Kalman output')
>>> ht = plt.plot(truth,'g-', label='true voltage')
>>> h = plt.legend()
>>> h = plt.title('Automobile Voltimeter Example')
>>> h1 = plt.title('Automobile Voltimeter Example')
>>> plt.show()
'''
def __init__(self, R, x=None, P=None, A=None, B=0, u=0, Q=None, H=None):
self.R = R
self.x = x
self.P = P
self.u = u
self.A = A
self.B = B
self.Q = Q
self.H = H
def __init__(self, R, x=None, P=None, A=None, B=0, Q=None, H=None):
self.R = R # Estimated error in measurements.
self.x = x # Initial state estimate.
self.P = P # Initial covariance estimate.
self.A = A # State transition matrix.
self.B = B # Control matrix.
self.Q = Q # Estimated error in process.
self.H = H # Observation matrix.
self.reset()
def reset(self):
self._filter = self._filter_first
def _filter_first(self, z):
def _filter_first(self, z, u):
self._filter = self._filter_main
@ -329,57 +410,68 @@ class Kalman(object):
else:
n = np.size(self.x)
if self.A is None:
self.A = np.eye(n, n)
self.A = np.eye(n)
self.A = np.atleast_2d(self.A)
if self.Q is None:
self.Q = np.zeros((n, n))
self.Q = np.atleast_2d(self.Q)
if self.H is None:
self.H = np.eye(n, n)
self.H = np.eye(n)
self.H = np.atleast_2d(self.H)
# if np.diff(np.shape(self.H)):
# raise ValueError('Observation matrix must be square and invertible for state autointialization.')
try:
HI = np.linalg.inv(self.H)
except:
HI = np.eye(n)
if self.P is None:
self.P = np.dot(np.dot(HI, self.R), HI.T)
self.P = np.atleast_2d(self.P)
if auto_init:
#initialize state estimate from first observation
# initialize state estimate from first observation
self.x = np.dot(HI, z)
return self.x
else:
return self._filter_main(z)
return self._filter_main(z, u)
def _predict_state(self, x, u):
return np.dot(self.A, x) + np.dot(self.B, u)
def _filter_main(self, z):
''' This is the code which implements the discrete Kalman filter:
'''
def _predict_covariance(self, P):
A = self.A
return np.dot(np.dot(A, P), A.T) + self.Q
def _compute_gain(self, P):
"""Kalman gain factor."""
H = self.H
P = self.P
PHT = np.dot(P, H.T)
innovation_covariance = np.dot(H, PHT) + self.R
#return np.linalg.solve(PHT, innovation_covariance)
return np.dot(PHT, np.linalg.inv(innovation_covariance))
# Prediction for state vector and covariance:
x = np.dot(A, self.x) + np.dot(self.B, self.u)
P = np.dot(np.dot(A, P), A.T) + self.Q
def _update_state_from_observation(self, x, z, K):
innovation = z - np.dot(self.H, x)
return x + np.dot(K, innovation)
# Compute Kalman gain factor:
PHT = np.dot(P, H.T)
K = np.dot(PHT, np.linalg.inv(np.dot(H, PHT) + self.R))
def _update_covariance(self, P, K):
return P - np.dot(K, np.dot(self.H, P))
return np.dot(np.eye(len(P)) - K * self.H, P)
# Correction based on observation:
self.x = x + np.dot(K, z - np.dot(H, x))
self.P = P - np.dot(K, np.dot(H, P))
def _filter_main(self, z, u):
''' This is the code which implements the discrete Kalman filter:
'''
P = self._predict_covariance(self.P)
x = self._predict_state(self.x, u)
# Note that the desired result, which is an improved estimate
# of the system state vector x and its covariance P, was obtained
# in only five lines of code, once the system was defined. (That's
# how simple the discrete Kalman filter is to use.) Later,
# we'll discuss how to deal with nonlinear systems.
K = self._compute_gain(P)
self.P = self._update_covariance(P, K)
self.x = self._update_state_from_observation(x, z, K)
return self.x
def __call__(self, z):
return self._filter(z)
def __call__(self, z, u=0):
return self._filter(z, u)
def test_kalman():
V0 = 12
@ -388,7 +480,7 @@ def test_kalman():
r = 0.05 ** 2 # variance of measurement error
b = 0 # no system input
u = 0 # no system input
filt = Kalman(R=r, A=1, Q=q, H=h, B=b, u=u)
filt = Kalman(R=r, A=1, Q=q, H=h, B=b)
# Generate random voltages and watch the filter operate.
n = 50
@ -397,32 +489,450 @@ def test_kalman():
x = np.zeros(n)
for i, zi in enumerate(z):
x[i] = filt(zi) # perform a Kalman filter iteration
x[i] = filt(zi, u) # perform a Kalman filter iteration
import matplotlib.pyplot as plt
_hz = plt.plot(z, 'r.', label='observations')
_hx = plt.plot(x, 'b-', label='Kalman output') # a-posteriori state estimates:
# a-posteriori state estimates:
_hx = plt.plot(x, 'b-', label='Kalman output')
_ht = plt.plot(truth, 'g-', label='true voltage')
plt.legend()
plt.title('Automobile Voltimeter Example')
plt.show('hold')
def lti_disc(F, L=None, Q=None, dt=1):
'''
LTI_DISC Discretize LTI ODE with Gaussian Noise
Syntax:
[A,Q] = lti_disc(F,L,Qc,dt)
In:
F - NxN Feedback matrix
L - NxL Noise effect matrix (optional, default identity)
Qc - LxL Diagonal Spectral Density (optional, default zeros)
dt - Time Step (optional, default 1)
Out:
A - Transition matrix
Q - Discrete Process Covariance
Description:
Discretize LTI ODE with Gaussian Noise. The original
ODE model is in form
dx/dt = F x + L w, w ~ N(0,Qc)
Result of discretization is the model
x[k] = A x[k-1] + q, q ~ N(0,Q)
Which can be used for integrating the model
exactly over time steps, which are multiples
of dt.
'''
n = np.shape(F)[0]
if L is None:
L = np.eye(n)
if Q is None:
Q = np.zeros((n, n))
# Closed form integration of transition matrix
A = expm(F * dt)
# Closed form integration of covariance
# by matrix fraction decomposition
Phi = np.vstack((np.hstack((F, np.dot(np.dot(L, Q), L.T))),
np.hstack((np.zeros((n, n)), -F.T))))
AB = np.dot(expm(Phi * dt), np.vstack((np.zeros((n, n)), np.eye(n))))
#Q = AB[:n, :] / AB[n:(2 * n), :]
Q = np.linalg.solve(AB[n:(2 * n), :].T, AB[:n, :].T)
return A, Q
def test_kalman_sine():
'''Kalman Filter demonstration with sine signal.'''
sd = 1.
dt = 0.1
w = 1
T = np.arange(0, 30 + dt / 2, dt)
n = len(T)
X = np.sin(w * T)
Y = X + sd * np.random.randn(n)
''' Initialize KF to values
x = 0
dx/dt = 0
with great uncertainty in derivative
'''
M = np.zeros((2, 1))
P = np.diag([0.1, 2])
R = sd ** 2
H = np.atleast_2d([1, 0])
q = 0.1
F = np.atleast_2d([[0, 1],
[0, 0]])
A, Q = lti_disc(F, L=None, Q=np.diag([0, q]), dt=dt)
# Track and animate
m = M.shape[0]
MM = np.zeros((m, n))
PP = np.zeros((m, m, n))
'''In this demonstration we estimate a stationary sine signal from noisy
measurements by using the classical Kalman filter.'
'''
filt = Kalman(R=R, x=M, P=P, A=A, Q=Q, H=H, B=0)
# Generate random voltages and watch the filter operate.
#n = 50
#truth = np.random.randn(n) * np.sqrt(q) + V0
#z = truth + np.random.randn(n) * np.sqrt(r) # measurement
truth = X
z = Y
x = np.zeros((n, m))
for i, zi in enumerate(z):
x[i] = filt(zi, u=0).ravel()
import matplotlib.pyplot as plt
_hz = plt.plot(z, 'r.', label='observations')
# a-posteriori state estimates:
_hx = plt.plot(x[:, 0], 'b-', label='Kalman output')
_ht = plt.plot(truth, 'g-', label='true voltage')
plt.legend()
plt.title('Automobile Voltimeter Example')
plt.show()
# for k in range(m):
# [M,P] = kf_predict(M,P,A,Q);
# [M,P] = kf_update(M,P,Y(k),H,R);
#
# MM(:,k) = M;
# PP(:,:,k) = P;
#
# %
# % Animate
# %
# if rem(k,10)==1
# plot(T,X,'b--',...
# T,Y,'ro',...
# T(k),M(1),'k*',...
# T(1:k),MM(1,1:k),'k-');
# legend('Real signal','Measurements','Latest estimate','Filtered estimate')
# title('Estimating a noisy sine signal with Kalman filter.');
# drawnow;
#
# pause;
# end
# end
#
# clc;
# disp('In this demonstration we estimate a stationary sine signal from noisy measurements by using the classical Kalman filter.');
# disp(' ');
# disp('The filtering results are now displayed sequantially for 10 time step at a time.');
# disp(' ');
# disp('<push any key to see the filtered and smoothed results together>')
# pause;
# %
# % Apply Kalman smoother
# %
# SM = rts_smooth(MM,PP,A,Q);
# plot(T,X,'b--',...
# T,MM(1,:),'k-',...
# T,SM(1,:),'r-');
# legend('Real signal','Filtered estimate','Smoothed estimate')
# title('Filtered and smoothed estimate of the original signal');
#
# clc;
# disp('The filtered and smoothed estimates of the signal are now displayed.')
# disp(' ');
# disp('RMS errors:');
# %
# % Errors
# %
# fprintf('KF = %.3f\nRTS = %.3f\n',...
# sqrt(mean((MM(1,:)-X(1,:)).^2)),...
# sqrt(mean((SM(1,:)-X(1,:)).^2)));
class HampelFilter(object):
'''
Hampel Filter.
HAMPEL(X,Y,DX,T,varargin) returns the Hampel filtered values of the
elements in Y. It was developed to detect outliers in a time series,
but it can also be used as an alternative to the standard median
filter.
X,Y are row or column vectors with an equal number of elements.
The elements in Y should be Gaussian distributed.
Parameters
----------
dx : positive scalar (default 3 * median(diff(X))
which defines the half width of the filter window. Dx should be
dimensionally equivalent to the values in X.
t : positive scalar (default 3)
which defines the threshold value used in the equation
|Y - Y0| > T * S0.
adaptive: real scalar
if greater than 0 it uses an experimental adaptive Hampel filter.
If none it uses a standard Hampel filter
fulloutput: bool
if True also the vectors: outliers, Y0,LB,UB,ADX, which corresponds to
the mask of the replaced values, nominal data, lower and upper bounds
on the Hampel filter and the relative half size of the local window,
respectively. outliers.sum() gives the number of outliers detected.
Examples
---------
Hampel filter removal of outliers
>>> import numpy as np
>>> randint = np.random.randint
>>> Y = 5000 + np.random.randn(1000)
>>> outliers = randint(0,1000, size=(10,))
>>> Y[outliers] = Y[outliers] + randint(1000, size=(10,))
>>> YY, res = HampelFilter(fulloutput=True)(Y)
>>> YY1, res1 = HampelFilter(dx=1, t=3, adaptive=0.1, fulloutput=True)(Y)
>>> YY2, res2 = HampelFilter(dx=3, t=0, fulloutput=True)(Y) # Y0 = median
X = np.arange(len(YY))
plt.plot(X, Y, 'b.') # Original Data
plt.plot(X, YY, 'r') # Hampel Filtered Data
plt.plot(X, res['Y0'], 'b--') # Nominal Data
plt.plot(X, res['LB'], 'r--') # Lower Bounds on Hampel Filter
plt.plot(X, res['UB'], 'r--') # Upper Bounds on Hampel Filter
i = res['outliers']
plt.plot(X[i], Y[i], 'ks') # Identified Outliers
plt.show('hold')
References
----------
Chapters 1.4.2, 3.2.2 and 4.3.4 in Mining Imperfect Data: Dealing with
Contamination and Incomplete Records by Ronald K. Pearson.
Acknowledgements
I would like to thank Ronald K. Pearson for the introduction to moving
window filters. Please visit his blog at:
http://exploringdatablog.blogspot.com/2012/01/moving-window-filters-and
-pracma.html
'''
def __init__(self, dx=None, t=3, adaptive=None, fulloutput=False):
self.dx = dx
self.t = t
self.adaptive = adaptive
self.fulloutput = fulloutput
def __call__(self, y, x=None):
Y = np.atleast_1d(y).ravel()
if x is None:
x = range(len(Y))
X = np.atleast_1d(x).ravel()
dx = self.dx
if dx is None:
dx = 3 * np.median(np.diff(X))
if not np.isscalar(dx):
raise ValueError('DX must be a scalar.')
elif dx < 0:
raise ValueError('DX must be larger than zero.')
YY = Y
S0 = np.nan * np.zeros(YY.shape)
Y0 = np.nan * np.zeros(YY.shape)
ADX = dx * np.ones(Y.shape)
def localwindow(X, Y, DX, i):
mask = (X[i] - DX <= X) & (X <= X[i] + DX)
Y0 = np.median(Y[mask])
# Calculate Local Scale of Natural Variation
S0 = 1.4826 * np.median(np.abs(Y[mask] - Y0))
return Y0, S0
def smgauss(X, V, DX):
Xj = X
Xk = np.atleast_2d(X).T
Wjk = np.exp(-((Xj - Xk) / (2 * DX)) ** 2)
G = np.dot(Wjk, V) / np.sum(Wjk, axis=0)
return G
if len(X) > 1:
if self.adaptive is None:
for i in range(len(Y)):
Y0[i], S0[i] = localwindow(X, Y, dx, i)
else: # 'adaptive'
Y0Tmp = np.nan * np.zeros(YY.shape)
S0Tmp = np.nan * np.zeros(YY.shape)
DXTmp = np.arange(1, len(S0) + 1) * dx
# Integer variation of Window Half Size
# Calculate Initial Guess of Optimal Parameters Y0, S0, ADX
for i in range(len(Y)):
j = 0
S0Rel = np.inf
while S0Rel > self.adaptive:
Y0Tmp[j], S0Tmp[j] = localwindow(X, Y, DXTmp[j], i)
if j > 0:
S0Rel = abs((S0Tmp[j - 1] - S0Tmp[j]) /
(S0Tmp[j - 1] + S0Tmp[j]) / 2)
j += 1
Y0[i] = Y0Tmp[j - 2]
S0[i] = S0Tmp[j - 2]
ADX[i] = DXTmp[j - 2] / dx
# Gaussian smoothing of relevant parameters
DX = 2 * np.median(np.diff(X))
ADX = smgauss(X, ADX, DX)
S0 = smgauss(X, S0, DX)
Y0 = smgauss(X, Y0, DX)
T = self.t
## Prepare Output
self.UB = Y0 + T * S0
self.LB = Y0 - T * S0
outliers = np.abs(Y - Y0) > T * S0 # possible outliers
YY[outliers] = Y0[outliers]
self.outliers = outliers
self.num_outliers = outliers.sum()
self.ADX = ADX
self.Y0 = Y0
if self.fulloutput:
return YY, dict(outliers=outliers, Y0=Y0,
LB=self.LB, UB=self.UB, ADX=ADX)
return YY
def test_hampel():
import matplotlib.pyplot as plt
randint = np.random.randint
Y = 5000 + np.random.randn(1000)
outliers = randint(0, 1000, size=(10,))
Y[outliers] = Y[outliers] + randint(1000, size=(10,))
YY, res = HampelFilter(dx=3, t=3, fulloutput=True)(Y)
YY1, res1 = HampelFilter(dx=1, t=3, adaptive=0.1, fulloutput=True)(Y)
YY2, res2 = HampelFilter(dx=3, t=0, fulloutput=True)(Y) # median
plt.figure(1)
plot_hampel(Y, YY, res)
plt.title('Standard HampelFilter')
plt.figure(2)
plot_hampel(Y, YY1, res1)
plt.title('Adaptive HampelFilter')
plt.figure(3)
plot_hampel(Y, YY2, res2)
plt.title('Median filter')
plt.show('hold')
def plot_hampel(Y, YY, res):
import matplotlib.pyplot as plt
X = np.arange(len(YY))
plt.plot(X, Y, 'b.') # Original Data
plt.plot(X, YY, 'r') # Hampel Filtered Data
plt.plot(X, res['Y0'], 'b--') # Nominal Data
plt.plot(X, res['LB'], 'r--') # Lower Bounds on Hampel Filter
plt.plot(X, res['UB'], 'r--') # Upper Bounds on Hampel Filter
i = res['outliers']
plt.plot(X[i], Y[i], 'ks') # Identified Outliers
#plt.show('hold')
def test_tide_filter():
# import statsmodels.api as sa
import wafo.spectrum.models as sm
sd = 10
Sj = sm.Jonswap(Hm0=4.* sd)
S = Sj.tospecdata()
q = (0.1 * sd) ** 2 # variance of process noise s the car operates
r = (100 * sd) ** 2 # variance of measurement error
b = 0 # no system input
u = 0 # no system input
from scipy.signal import butter, lfilter, filtfilt, lfilter_zi
freq_tide = 1. / (12 * 60 * 60)
freq_wave = 1. / 10
freq_filt = freq_wave / 10
dt = 1.
freq = 1. / dt
fn = (freq / 2)
P = 10* np.diag([1, 0.01])
R = r
H = np.atleast_2d([1, 0])
F = np.atleast_2d([[0, 1],
[0, 0]])
A, Q = lti_disc(F, L=None, Q=np.diag([0, q]), dt=dt)
t = np.arange(0, 60 * 12, 1. / freq)
w = 2 * np.pi * freq # 1 Hz
tide = 100 * np.sin(freq_tide * w * t + 2 * np.pi / 4) + 100
y = tide + S.sim(len(t), dt=1. / freq)[:, 1].ravel()
# lowess = sa.nonparametric.lowess
# y2 = lowess(y, t, frac=0.5)[:,1]
filt = Kalman(R=R, x=np.array([[tide[0]], [0]]), P=P, A=A, Q=Q, H=H, B=b)
filt2 = Kalman(R=R, x=np.array([[tide[0]], [0]]), P=P, A=A, Q=Q, H=H, B=b)
#y = tide + 0.5 * np.sin(freq_wave * w * t)
# Butterworth filter
b, a = butter(9, (freq_filt / fn), btype='low')
#y2 = [lowess(y[max(i-60,0):i + 1], t[max(i-60,0):i + 1], frac=.3)[-1,1] for i in range(len(y))]
#y2 = [lfilter(b, a, y[:i + 1])[i] for i in range(len(y))]
#y3 = filtfilt(b, a, y[:16]).tolist() + [filtfilt(b, a, y[:i + 1])[i] for i in range(16, len(y))]
#y0 = medfilt(y, 41)
zi = lfilter_zi(b, a)
#y2 = lfilter(b, a, y)#, zi=y[0]*zi) # standard filter
y3 = filtfilt(b, a, y) # filter with phase shift correction
y4 =[]
y5 = []
for i, j in enumerate(y):
tmp = filt(j, u=u).ravel()
tmp = filt2(tmp[0], u=u).ravel()
# if i==0:
# print(filt.x)
# print(filt2.x)
y4.append(tmp[0])
y5.append(tmp[1])
y0 = medfilt(y4, 41)
print(filt.P)
# plot
import matplotlib.pyplot as plt
plt.plot(t, y, 'r.-', linewidth=2, label='raw data')
#plt.plot(t, y2, 'b.-', linewidth=2, label='lowess @ %g Hz' % freq_filt)
#plt.plot(t, y2, 'b.-', linewidth=2, label='filter @ %g Hz' % freq_filt)
plt.plot(t, y3, 'g.-', linewidth=2, label='filtfilt @ %g Hz' % freq_filt)
plt.plot(t, y4, 'k.-', linewidth=2, label='kalman')
#plt.plot(t, y5, 'k.', linewidth=2, label='kalman2')
plt.plot(t, tide, 'y-', linewidth=2, label='True tide')
plt.legend(frameon=False, fontsize=14)
plt.xlabel("Time [s]")
plt.ylabel("Amplitude")
plt.show('hold')
def test_smooth():
import matplotlib.pyplot as plt
t = np.linspace(-4, 4, 500)
y = np.exp(-t ** 2) + np.random.normal(0, 0.05, t.shape)
coeff = calc_coeff(num_points=3, degree=2, diff_order=0)
coeff = calc_coeff(n=0, degree=0, diff_order=0)
ysg = smooth(y, coeff, pad=True)
plt.plot(t, y, t, ysg, '--')
plt.show()
def test_docstrings():
import doctest
doctest.testmod()
print('Testing docstrings in %s' % __file__)
doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
if __name__ == '__main__':
test_docstrings()
#test_kalman_sine()
test_tide_filter()
#test_docstrings()
#test_hampel()
#test_kalman()
#test_smooth()
# test_smooth()

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,76 +1,133 @@
import unittest
import numpy as np
from wafo.spectrum.models import (Bretschneider, Jonswap, OchiHubble, Tmaspec,
Torsethaugen, McCormick, Wallop)
Torsethaugen, McCormick, Wallop, Spreading)
def test_bretschneider():
S = Bretschneider(Hm0=6.5, Tp=10)
vals = S((0, 1, 2, 3))
true_vals = np.array([0., 1.69350993, 0.06352698, 0.00844783])
assert((np.abs(vals - true_vals) < 1e-7).all())
class TestCase(unittest.TestCase):
def assertListAlmostEqual(self, list1, list2, places=None, msg=None):
self.assertEqual(len(list1), len(list2))
for a, b in zip(list1, list2):
self.assertAlmostEqual(a, b, places, msg)
def test_if_jonswap_with_gamma_one_equals_bretschneider():
class TestSpectra(TestCase):
def test_bretschneider(self):
S = Bretschneider(Hm0=6.5, Tp=10)
vals = S((0, 1, 2, 3)).tolist()
true_vals = [0., 1.69350993, 0.06352698, 0.00844783]
self.assertListAlmostEqual(vals, true_vals)
def test_if_jonswap_with_gamma_one_equals_bretschneider(self):
S = Jonswap(Hm0=7, Tp=11, gamma=1)
vals = S((0, 1, 2, 3))
true_vals = np.array([0., 1.42694133, 0.05051648, 0.00669692])
assert((np.abs(vals - true_vals) < 1e-7).all())
self.assertListAlmostEqual(vals, true_vals)
w = np.linspace(0, 5)
S2 = Bretschneider(Hm0=7, Tp=11)
# JONSWAP with gamma=1 should be equal to Bretscneider:
assert(np.all(np.abs(S(w) - S2(w)) < 1.e-7))
self.assertListAlmostEqual(S(w), S2(w))
def test_tmaspec():
def test_tmaspec(self):
S = Tmaspec(Hm0=7, Tp=11, gamma=1, h=10)
vals = S((0, 1, 2, 3))
true_vals = np.array([0., 0.70106233, 0.05022433, 0.00669692])
assert((np.abs(vals - true_vals) < 1e-7).all())
def test_torsethaugen():
self.assertListAlmostEqual(vals, true_vals)
def test_torsethaugen(self):
S = Torsethaugen(Hm0=7, Tp=11, gamma=1, h=10)
vals = S((0, 1, 2, 3))
true_vals = np.array([0., 1.19989709, 0.05819794, 0.0093541])
assert((np.abs(vals - true_vals) < 1e-7).all())
self.assertListAlmostEqual(vals, true_vals)
vals = S.wind(range(4))
true_vals = np.array([0., 1.13560528, 0.05529849, 0.00888989])
assert((np.abs(vals - true_vals) < 1e-7).all())
self.assertListAlmostEqual(vals, true_vals)
vals = S.swell(range(4))
true_vals = np.array([0., 0.0642918, 0.00289946, 0.00046421])
assert((np.abs(vals - true_vals) < 1e-7).all())
self.assertListAlmostEqual(vals, true_vals)
def test_ochihubble():
def test_ochihubble(self):
S = OchiHubble(par=2)
vals = S(range(4))
true_vals = np.array([0., 0.90155636, 0.04185445, 0.00583207])
assert((np.abs(vals - true_vals) < 1e-7).all())
self.assertListAlmostEqual(vals, true_vals)
def test_mccormick():
def test_mccormick(self):
S = McCormick(Hm0=6.5, Tp=10)
vals = S(range(4))
true_vals = np.array([0., 1.87865908, 0.15050447, 0.02994663])
assert((np.abs(vals - true_vals) < 1e-7).all())
def test_wallop():
self.assertListAlmostEqual(vals, true_vals)
def test_wallop(self):
S = Wallop(Hm0=6.5, Tp=10)
vals = S(range(4))
true_vals = np.array([0.00000000e+00, 9.36921871e-01, 2.76991078e-03,
7.72996150e-05])
assert((np.abs(vals - true_vals) < 1e-7).all())
self.assertListAlmostEqual(vals, true_vals)
class TestSpreading(TestCase):
def test_cos2s(self):
theta = np.linspace(0, 2 * np.pi)
d = Spreading(type='cos2s')
dvals = [[1.10168934e+00],
[1.03576796e+00],
[8.60302298e-01],
[6.30309013e-01],
[4.06280137e-01],
[2.29514882e-01],
[1.13052757e-01],
[4.82339343e-02],
[1.76754409e-02],
[5.50490020e-03],
[1.43800617e-03],
[3.09907242e-04],
[5.39672445e-05],
[7.39553743e-06],
[7.70796579e-07],
[5.84247670e-08],
[3.03264905e-09],
[9.91950201e-11],
[1.81442131e-12],
[1.55028269e-14],
[4.63223469e-17],
[2.90526245e-20],
[1.35842977e-24],
[3.26077455e-31],
[1.65021852e-45],
[1.65021852e-45],
[3.26077455e-31],
[1.35842977e-24],
[2.90526245e-20],
[4.63223469e-17],
[1.55028269e-14],
[1.81442131e-12],
[9.91950201e-11],
[3.03264905e-09],
[5.84247670e-08],
[7.70796579e-07],
[7.39553743e-06],
[5.39672445e-05],
[3.09907242e-04],
[1.43800617e-03],
[5.50490020e-03],
[1.76754409e-02],
[4.82339343e-02],
[1.13052757e-01],
[2.29514882e-01],
[4.06280137e-01],
[6.30309013e-01],
[8.60302298e-01],
[1.03576796e+00],
[1.10168934e+00]]
self.assertListAlmostEqual(d(theta)[0], dvals)
if __name__ == '__main__':
# main()
import nose
nose.run()
#test_tmaspec()
unittest.main()

@ -1,4 +1,6 @@
import wafo.spectrum.models as sm
import wafo.transform.models as wtm
import wafo.objects as wo
from wafo.spectrum import SpecData1D
import numpy as np
import unittest
@ -18,11 +20,11 @@ class TestSpectrum(unittest.TestCase):
acfmat = S.tocov_matrix(nr=3, nt=256, dt=0.1)
vals = acfmat[:2, :]
true_vals = np.array([[3.06073383, 0.0000000, -1.67748256, 0.],
[3.05235423, -0.1674357, -1.66811444, 0.18693242]])
[3.05235423, -0.1674357, -1.66811444,
0.18693242]])
self.assertTrue((np.abs(vals - true_vals) < 1e-7).all())
def test_tocovdata():
Sj = sm.Jonswap()
S = Sj.tospecdata()
@ -41,22 +43,25 @@ def test_to_t_pdf():
f = S.to_t_pdf(pdef='Tc', paramt=(0, 10, 51), speed=7, seed=100)
vals = ['%2.3f' % val for val in f.data[:10]]
truevals = ['0.000', '0.014', '0.027', '0.040',
'0.050', '0.059', '0.067', '0.072', '0.077', '0.081']
'0.050', '0.059', '0.067', '0.073', '0.077', '0.082']
for t, v in zip(truevals, vals):
assert(t == v)
# estimated error bounds
vals = ['%2.4f' % val for val in f.err[:10]]
truevals = ['0.0000', '0.0003', '0.0003', '0.0004',
'0.0006', '0.0009', '0.0016', '0.0019', '0.0020', '0.0021']
'0.0006', '0.0008', '0.0016', '0.0019', '0.0020', '0.0021']
for t, v in zip(truevals, vals):
assert(t == v)
@slow
def test_sim():
Sj = sm.Jonswap()
S = Sj.tospecdata()
ns = 100
dt = .2
x1 = S.sim(ns, dt=dt)
#ns = 100
#dt = .2
#x1 = S.sim(ns, dt=dt)
import scipy.stats as st
x2 = S.sim(20000, 20)
@ -75,13 +80,11 @@ def test_sim_nl():
Sj = sm.Jonswap()
S = Sj.tospecdata()
ns = 100
dt = .2
x1 = S.sim_nl(ns, dt=dt)
import numpy as np
# ns = 100
# dt = .2
# x1 = S.sim_nl(ns, dt=dt)
import scipy.stats as st
x2, x1 = S.sim_nl(ns=20000, cases=40)
x2, _x1 = S.sim_nl(ns=20000, cases=40)
truth1 = [0, np.sqrt(S.moment(1)[0][0])] + S.stats_nl(moments='sk')
truth1[-1] = truth1[-1] - 3
@ -110,26 +113,22 @@ def test_stats_nl():
def test_testgaussian():
'''
>>> import wafo.spectrum.models as sm
>>> import wafo.transform.models as wtm
>>> import wafo.objects as wo
>>> Hs = 7
>>> Sj = sm.Jonswap(Hm0=Hs)
>>> S0 = Sj.tospecdata()
>>> ns =100; dt = .2
>>> x1 = S0.sim(ns, dt=dt)
>>> S = S0.copy()
>>> me, va, sk, ku = S.stats_nl(moments='mvsk')
>>> S.tr = wtm.TrHermite(mean=me, sigma=Hs/4, skew=sk, kurt=ku, ysigma=Hs/4)
>>> ys = wo.mat2timeseries(S.sim(ns=2**13))
>>> g0, gemp = ys.trdata()
>>> t0 = g0.dist2gauss()
>>> t1 = S0.testgaussian(ns=2**13, t0=t0, cases=50)
>>> sum(t1>t0)<5
True
'''
Hs = 7
Sj = sm.Jonswap(Hm0=Hs)
S0 = Sj.tospecdata()
#ns =100; dt = .2
#x1 = S0.sim(ns, dt=dt)
S = S0.copy()
me, _va, sk, ku = S.stats_nl(moments='mvsk')
S.tr = wtm.TrHermite(
mean=me, sigma=Hs / 4, skew=sk, kurt=ku, ysigma=Hs / 4)
ys = wo.mat2timeseries(S.sim(ns=2 ** 13))
g0, _gemp = ys.trdata()
t0 = g0.dist2gauss()
t1 = S0.testgaussian(ns=2 ** 13, t0=t0, cases=50)
assert(sum(t1 > t0) < 5)
def test_moment():
@ -140,29 +139,28 @@ def test_moment():
true_txt = ['m0', 'm0tt']
for tv, v in zip(true_vals, vals):
assert(tv == v)
for tv, v in zip(true_txt, txt):
assert(tv == v)
def test_nyquist_freq():
Sj = sm.Jonswap(Hm0=5)
S = Sj.tospecdata() # Make spectrum ob
assert(S.nyquist_freq() == 3.0)
def test_sampling_period():
Sj = sm.Jonswap(Hm0=5)
S = Sj.tospecdata() # Make spectrum ob
assert(S.sampling_period() == 1.0471975511965976)
def test_normalize():
Sj = sm.Jonswap(Hm0=5)
S = Sj.tospecdata() # Make spectrum ob
S.moment(2)
([1.5614600345079888, 0.95567089481941048], ['m0', 'm0tt'])
vals, txt = S.moment(2)
vals, _txt = S.moment(2)
true_vals = [1.5614600345079888, 0.95567089481941048]
for tv, v in zip(true_vals, vals):
assert(tv == v)
@ -171,7 +169,7 @@ def test_normalize():
Sn.normalize()
# Now the moments should be one
new_vals, txt = Sn.moment(2)
new_vals, _txt = Sn.moment(2)
for v in new_vals:
assert(np.abs(v - 1.0) < 1e-7)

@ -8,7 +8,7 @@ Statistical functions (:mod:`scipy.stats`)
This module contains a large number of probability distributions as
well as a growing library of statistical functions.
Each included distribution is an instance of the class rv_continous:
Each included distribution is an instance of the class rv_continuous:
For each given name the following methods are available:
.. autosummary::
@ -77,7 +77,7 @@ Continuous distributions
exponweib -- Exponentiated Weibull
exponpow -- Exponential Power
f -- F (Snecdor F)
fatiguelife -- Fatigue Life (Birnbaum-Sanders)
fatiguelife -- Fatigue Life (Birnbaum-Saunders)
fisk -- Fisk
foldcauchy -- Folded Cauchy
foldnorm -- Folded Normal
@ -149,6 +149,7 @@ Multivariate distributions
:toctree: generated/
multivariate_normal -- Multivariate normal distribution
dirichlet -- Dirichlet
Discrete distributions
======================
@ -231,6 +232,7 @@ which work for masked arrays.
.. autosummary::
:toctree: generated/
sigmaclip
threshold
trimboth
trim1
@ -244,6 +246,7 @@ which work for masked arrays.
pointbiserialr
kendalltau
linregress
theilslopes
.. autosummary::
:toctree: generated/
@ -271,8 +274,10 @@ which work for masked arrays.
levene
shapiro
anderson
anderson_ksamp
binom_test
fligner
median_test
mood
.. autosummary::
@ -282,6 +287,8 @@ which work for masked arrays.
boxcox_normmax
boxcox_llf
entropy
Contingency table functions
===========================
@ -344,3 +351,5 @@ __all__ = [s for s in dir() if not (s.startswith('_') or s.endswith('cython'))]
#import distributions #@Reimport
#from wafo.stats.distributions import *
from numpy.testing import Tester
test = Tester().test

@ -16,8 +16,6 @@ def binned_statistic(x, values, statistic='mean',
each bin. This function allows the computation of the sum, mean, median,
or other statistic of the values within each bin.
.. versionadded:: 0.11.0
Parameters
----------
x : array_like
@ -78,6 +76,8 @@ def binned_statistic(x, values, statistic='mean',
second ``[2, 3)``. The last bin, however, is ``[3, 4]``, which *includes*
4.
.. versionadded:: 0.11.0
Examples
--------
>>> stats.binned_statistic([1, 2, 1, 2, 4], np.arange(5), statistic='mean',
@ -116,8 +116,6 @@ def binned_statistic_2d(x, y, values, statistic='mean',
each bin. This function allows the computation of the sum, mean, median,
or other statistic of the values within each bin.
.. versionadded:: 0.11.0
Parameters
----------
x : (N,) array_like
@ -175,6 +173,11 @@ def binned_statistic_2d(x, y, values, statistic='mean',
--------
numpy.histogram2d, binned_statistic, binned_statistic_dd
Notes
-----
.. versionadded:: 0.11.0
"""
# This code is based on np.histogram2d
@ -203,8 +206,6 @@ def binned_statistic_dd(sample, values, statistic='mean',
each bin. This function allows the computation of the sum, mean, median,
or other statistic of the values within each bin.
.. versionadded:: 0.11.0
Parameters
----------
sample : array_like
@ -258,6 +259,11 @@ def binned_statistic_dd(sample, values, statistic='mean',
--------
np.histogramdd, binned_statistic, binned_statistic_2d
Notes
-----
.. versionadded:: 0.11.0
"""
if type(statistic) == str:
if statistic not in ['mean', 'median', 'count', 'sum', 'std']:

File diff suppressed because it is too large Load Diff

@ -13,17 +13,10 @@ import numpy as np
import numpy.random as mtrand
from ._distn_infrastructure import (
rv_discrete, _lazywhere, _ncx2_pdf, _ncx2_cdf)
__all__ = [
'binom', 'bernoulli', 'nbinom', 'geom', 'hypergeom',
'logser', 'poisson', 'planck', 'boltzmann', 'randint',
'zipf', 'dlaplace', 'skellam'
]
rv_discrete, _lazywhere, _ncx2_pdf, _ncx2_cdf, get_distribution_names)
class binom_gen(rv_discrete):
"""A binomial discrete random variable.
%(before_notes)s
@ -41,7 +34,6 @@ class binom_gen(rv_discrete):
%(example)s
"""
def _rvs(self, n, p):
return mtrand.binomial(n, p, self._size)
@ -51,8 +43,8 @@ class binom_gen(rv_discrete):
def _logpmf(self, x, n, p):
k = floor(x)
combiln = (gamln(n + 1) - (gamln(k + 1) + gamln(n - k + 1)))
return combiln + special.xlogy(k, p) + special.xlog1py(n - k, -p)
combiln = (gamln(n+1) - (gamln(k+1) + gamln(n-k+1)))
return combiln + special.xlogy(k, p) + special.xlog1py(n-k, -p)
def _pmf(self, x, n, p):
return exp(self._logpmf(x, n, p))
@ -68,16 +60,19 @@ class binom_gen(rv_discrete):
def _ppf(self, q, n, p):
vals = ceil(special.bdtrik(q, n, p))
vals1 = vals - 1
vals1 = np.maximum(vals - 1, 0)
temp = special.bdtr(vals1, n, p)
return np.where(temp >= q, vals1, vals)
def _stats(self, n, p):
def _stats(self, n, p, moments='mv'):
q = 1.0 - p
mu = n * p
var = n * p * q
g1 = (q - p) / sqrt(n * p * q)
g2 = (1.0 - 6 * p * q) / (n * p * q)
g1, g2 = None, None
if 's' in moments:
g1 = (q - p) / sqrt(var)
if 'k' in moments:
g2 = (1.0 - 6*p*q) / var
return mu, var, g1, g2
def _entropy(self, n, p):
@ -89,7 +84,6 @@ binom = binom_gen(name='binom')
class bernoulli_gen(binom_gen):
"""A Bernoulli discrete random variable.
%(before_notes)s
@ -108,7 +102,6 @@ class bernoulli_gen(binom_gen):
%(example)s
"""
def _rvs(self, p):
return binom_gen._rvs(self, 1, p)
@ -140,7 +133,6 @@ bernoulli = bernoulli_gen(b=1, name='bernoulli')
class nbinom_gen(rv_discrete):
"""A negative binomial discrete random variable.
%(before_notes)s
@ -158,7 +150,6 @@ class nbinom_gen(rv_discrete):
%(example)s
"""
def _rvs(self, n, p):
return mtrand.negative_binomial(n, p, self._size)
@ -174,7 +165,7 @@ class nbinom_gen(rv_discrete):
def _cdf(self, x, n, p):
k = floor(x)
return special.betainc(n, k + 1, p)
return special.betainc(n, k+1, p)
def _sf_skip(self, x, n, p):
# skip because special.nbdtrc doesn't work for 0<n<1
@ -183,23 +174,22 @@ class nbinom_gen(rv_discrete):
def _ppf(self, q, n, p):
vals = ceil(special.nbdtrik(q, n, p))
vals1 = (vals - 1).clip(0.0, np.inf)
vals1 = (vals-1).clip(0.0, np.inf)
temp = self._cdf(vals1, n, p)
return np.where(temp >= q, vals1, vals)
def _stats(self, n, p):
Q = 1.0 / p
P = Q - 1.0
mu = n * P
var = n * P * Q
g1 = (Q + P) / sqrt(n * P * Q)
g2 = (1.0 + 6 * P * Q) / (n * P * Q)
mu = n*P
var = n*P*Q
g1 = (Q+P)/sqrt(n*P*Q)
g2 = (1.0 + 6*P*Q) / (n*P*Q)
return mu, var, g1, g2
nbinom = nbinom_gen(name='nbinom')
class geom_gen(rv_discrete):
"""A geometric discrete random variable.
%(before_notes)s
@ -217,7 +207,6 @@ class geom_gen(rv_discrete):
%(example)s
"""
def _rvs(self, p):
return mtrand.geometric(p, size=self._size)
@ -225,7 +214,7 @@ class geom_gen(rv_discrete):
return (p <= 1) & (p >= 0)
def _pmf(self, k, p):
return np.power(1 - p, k - 1) * p
return np.power(1-p, k-1) * p
def _logpmf(self, k, p):
return (k - 1) * log1p(-p) + log(p)
@ -247,17 +236,16 @@ class geom_gen(rv_discrete):
return np.where((temp >= q) & (vals > 0), vals - 1, vals)
def _stats(self, p):
mu = 1.0 / p
qr = 1.0 - p
mu = 1.0/p
qr = 1.0-p
var = qr / p / p
g1 = (2.0 - p) / sqrt(qr)
g2 = np.polyval([1, -6, 6], p) / (1.0 - p)
g1 = (2.0-p) / sqrt(qr)
g2 = np.polyval([1, -6, 6], p)/(1.0-p)
return mu, var, g1, g2
geom = geom_gen(a=1, name='geom', longname="A geometric")
class hypergeom_gen(rv_discrete):
"""A hypergeometric discrete random variable.
The hypergeometric distribution models drawing objects from a bin.
@ -277,6 +265,7 @@ class hypergeom_gen(rv_discrete):
Examples
--------
>>> from scipy.stats import hypergeom
>>> import matplotlib.pyplot as plt
Suppose we have a collection of 20 animals, of which 7 are dogs. Then if
we want to know the probability of finding a given number of dogs if we
@ -307,23 +296,22 @@ class hypergeom_gen(rv_discrete):
>>> R = hypergeom.rvs(M, n, N, size=10)
"""
def _rvs(self, M, n, N):
return mtrand.hypergeometric(n, M - n, N, size=self._size)
return mtrand.hypergeometric(n, M-n, N, size=self._size)
def _argcheck(self, M, n, N):
cond = rv_discrete._argcheck(self, M, n, N)
cond &= (n <= M) & (N <= M)
self.a = max(N - (M - n), 0)
self.a = max(N-(M-n), 0)
self.b = min(n, N)
return cond
def _logpmf(self, k, M, n, N):
tot, good = M, n
bad = tot - good
return gamln(good + 1) - gamln(good - k + 1) - gamln(k + 1) + \
gamln(bad + 1) - gamln(bad - N + k + 1) - gamln(N - k + 1) - \
gamln(tot + 1) + gamln(tot - N + 1) + gamln(N + 1)
return gamln(good+1) - gamln(good-k+1) - gamln(k+1) + gamln(bad+1) \
- gamln(bad-N+k+1) - gamln(N-k+1) - gamln(tot+1) + gamln(tot-N+1) \
+ gamln(N+1)
def _pmf(self, k, M, n, N):
# same as the following but numerically more precise
@ -333,19 +321,18 @@ class hypergeom_gen(rv_discrete):
def _stats(self, M, n, N):
# tot, good, sample_size = M, n, N
# "wikipedia".replace('N', 'M').replace('n', 'N').replace('K', 'n')
M, n, N = 1. * M, 1. * n, 1. * N
M, n, N = 1.*M, 1.*n, 1.*N
m = M - n
p = n / M
mu = N * p
p = n/M
mu = N*p
var = m * n * N * (M - N) * 1.0 / (M * M * (M - 1))
g1 = (m - n) * (M - 2 * N) / (M - 2.0) * \
sqrt((M - 1.0) / (m * n * N * (M - N)))
var = m*n*N*(M - N)*1.0/(M*M*(M-1))
g1 = (m - n)*(M-2*N) / (M-2.0) * sqrt((M-1.0) / (m*n*N*(M-N)))
g2 = M * (M + 1) - 6. * N * (M - N) - 6. * n * m
g2 *= (M - 1) * M * M
g2 += 6. * n * N * (M - N) * m * (5. * M - 6)
g2 /= n * N * (M - N) * m * (M - 2.) * (M - 3.)
g2 = M*(M+1) - 6.*N*(M-N) - 6.*n*m
g2 *= (M-1)*M*M
g2 += 6.*n*N*(M-N)*m*(5.*M-6)
g2 /= n * N * (M-N) * m * (M-2.) * (M-3.)
return mu, var, g1, g2
def _entropy(self, M, n, N):
@ -372,7 +359,6 @@ hypergeom = hypergeom_gen(name='hypergeom')
# FIXME: Fails _cdfvec
class logser_gen(rv_discrete):
"""A Logarithmic (Log-Series, Series) discrete random variable.
%(before_notes)s
@ -390,7 +376,6 @@ class logser_gen(rv_discrete):
%(example)s
"""
def _rvs(self, p):
# looks wrong for p>0.5, too few k=1
# trying to use generic is worse, no k=1 at all
@ -405,22 +390,21 @@ class logser_gen(rv_discrete):
def _stats(self, p):
r = log1p(-p)
mu = p / (p - 1.0) / r
mu2p = -p / r / (p - 1.0) ** 2
var = mu2p - mu * mu
mu3p = -p / r * (1.0 + p) / (1.0 - p) ** 3
mu3 = mu3p - 3 * mu * mu2p + 2 * mu ** 3
mu2p = -p / r / (p - 1.0)**2
var = mu2p - mu*mu
mu3p = -p / r * (1.0+p) / (1.0 - p)**3
mu3 = mu3p - 3*mu*mu2p + 2*mu**3
g1 = mu3 / np.power(var, 1.5)
mu4p = -p / r * (
1.0 / (p - 1) ** 2 - 6 * p / (p - 1) ** 3 + 6 * p * p / (p - 1) ** 4)
mu4 = mu4p - 4 * mu3p * mu + 6 * mu2p * mu * mu - 3 * mu ** 4
g2 = mu4 / var ** 2 - 3.0
1.0 / (p-1)**2 - 6*p / (p - 1)**3 + 6*p*p / (p-1)**4)
mu4 = mu4p - 4*mu3p*mu + 6*mu2p*mu*mu - 3*mu**4
g2 = mu4 / var**2 - 3.0
return mu, var, g1, g2
logser = logser_gen(a=1, name='logser', longname='A logarithmic')
class poisson_gen(rv_discrete):
"""A Poisson discrete random variable.
%(before_notes)s
@ -438,12 +422,11 @@ class poisson_gen(rv_discrete):
%(example)s
"""
def _rvs(self, mu):
return mtrand.poisson(mu, self._size)
def _logpmf(self, k, mu):
Pk = k * log(mu) - gamln(k + 1) - mu
Pk = k*log(mu)-gamln(k+1) - mu
return Pk
def _pmf(self, k, mu):
@ -459,9 +442,9 @@ class poisson_gen(rv_discrete):
def _ppf(self, q, mu):
vals = ceil(special.pdtrik(q, mu))
vals1 = vals - 1
vals1 = np.maximum(vals - 1, 0)
temp = special.pdtr(vals1, mu)
return np.where((temp >= q), vals1, vals)
return np.where(temp >= q, vals1, vals)
def _stats(self, mu):
var = mu
@ -473,7 +456,6 @@ poisson = poisson_gen(name="poisson", longname='A Poisson')
class planck_gen(rv_discrete):
"""A Planck discrete exponential random variable.
%(before_notes)s
@ -491,7 +473,6 @@ class planck_gen(rv_discrete):
%(example)s
"""
def _argcheck(self, lambda_):
if (lambda_ > 0):
self.a = 0
@ -513,27 +494,26 @@ class planck_gen(rv_discrete):
return - expm1(-lambda_ * (k + 1))
def _ppf(self, q, lambda_):
vals = ceil(-1.0 / lambda_ * log1p(-q) - 1)
vals1 = (vals - 1).clip(self.a, np.inf)
vals = ceil(-1.0/lambda_ * log1p(-q)-1)
vals1 = (vals-1).clip(self.a, np.inf)
temp = self._cdf(vals1, lambda_)
return np.where(temp >= q, vals1, vals)
def _stats(self, lambda_):
mu = 1 / (exp(lambda_) - 1)
var = exp(-lambda_) / (expm1(-lambda_)) ** 2
g1 = 2 * cosh(lambda_ / 2.0)
g2 = 4 + 2 * cosh(lambda_)
mu = 1/(exp(lambda_)-1)
var = exp(-lambda_)/(expm1(-lambda_))**2
g1 = 2*cosh(lambda_/2.0)
g2 = 4+2*cosh(lambda_)
return mu, var, g1, g2
def _entropy(self, lambda_):
l = lambda_
C = -expm1(-l)
return l * exp(-l) / C - log(C)
return l*exp(-l)/C - log(C)
planck = planck_gen(name='planck', longname='A discrete exponential ')
class boltzmann_gen(rv_discrete):
"""A Boltzmann (Truncated Discrete Exponential) random variable.
%(before_notes)s
@ -551,7 +531,6 @@ class boltzmann_gen(rv_discrete):
%(example)s
"""
def _pmf(self, k, lambda_, N):
fact = (expm1(-lambda_)) / (expm1(-lambda_ * N))
return fact * exp(-lambda_ * k)
@ -569,15 +548,14 @@ class boltzmann_gen(rv_discrete):
def _stats(self, lambda_, N):
z = exp(-lambda_)
zN = exp(-lambda_ * N)
mu = z / (1.0 - z) - N * zN / (1 - zN)
var = z / (1.0 - z) ** 2 - N * N * zN / (1 - zN) ** 2
trm = (1 - zN) / (1 - z)
trm2 = (z * trm ** 2 - N * N * zN)
g1 = z * (1 + z) * trm ** 3 - N ** 3 * zN * (1 + zN)
g1 = g1 / trm2 ** (1.5)
g2 = z * (1 + 4 * z + z * z) * \
trm ** 4 - N ** 4 * zN * (1 + 4 * zN + zN * zN)
zN = exp(-lambda_*N)
mu = z/(1.0-z)-N*zN/(1-zN)
var = z/(1.0-z)**2 - N*N*zN/(1-zN)**2
trm = (1-zN)/(1-z)
trm2 = (z*trm**2 - N*N*zN)
g1 = z*(1+z)*trm**3 - N**3*zN*(1+zN)
g1 = g1 / trm2**(1.5)
g2 = z*(1+4*z+z*z)*trm**4 - N**4 * zN*(1+4*zN+zN*zN)
g2 = g2 / trm2 / trm2
return mu, var, g1, g2
boltzmann = boltzmann_gen(name='boltzmann',
@ -585,7 +563,6 @@ boltzmann = boltzmann_gen(name='boltzmann',
class randint_gen(rv_discrete):
"""A uniform discrete random variable.
%(before_notes)s
@ -606,7 +583,6 @@ class randint_gen(rv_discrete):
%(example)s
"""
def _argcheck(self, low, high):
self.a = low
self.b = high - 1
@ -630,9 +606,9 @@ class randint_gen(rv_discrete):
m2, m1 = np.asarray(high), np.asarray(low)
mu = (m2 + m1 - 1.0) / 2
d = m2 - m1
var = (d * d - 1) / 12.0
var = (d*d - 1) / 12.0
g1 = 0.0
g2 = -6.0 / 5.0 * (d * d + 1.0) / (d * d - 1.0)
g2 = -6.0/5.0 * (d*d + 1.0) / (d*d - 1.0)
return mu, var, g1, g2
def _rvs(self, low, high=None):
@ -648,9 +624,22 @@ randint = randint_gen(name='randint', longname='A discrete uniform '
'(random integer)')
def harmonic(n,r):
return 1./n + special.polygamma(r-1, n)/special.gamma(r) + special.zeta(r, 1)
def H(n):
"""Returns the n-th harmonic number.
http://en.wikipedia.org/wiki/Harmonic_number
"""
# Euler-Mascheroni constant
gamma = 0.57721566490153286060651209008240243104215933593992
return gamma + special.digamma(n+1)
# FIXME: problems sampling.
class zipf_gen(rv_discrete):
"""A Zipf discrete random variable.
%(before_notes)s
@ -668,7 +657,6 @@ class zipf_gen(rv_discrete):
%(example)s
"""
def _rvs(self, a):
return mtrand.zipf(a, size=self._size)
@ -676,7 +664,7 @@ class zipf_gen(rv_discrete):
return a > 1
def _pmf(self, k, a):
Pk = 1.0 / special.zeta(a, 1) / k ** a
Pk = 1.0 / special.zeta(a, 1) / k**a
return Pk
def _munp(self, n, a):
@ -688,7 +676,6 @@ zipf = zipf_gen(a=1, name='zipf', longname='A Zipf')
class dlaplace_gen(rv_discrete):
"""A Laplacian discrete random variable.
%(before_notes)s
@ -706,37 +693,35 @@ class dlaplace_gen(rv_discrete):
%(example)s
"""
def _pmf(self, k, a):
return tanh(a / 2.0) * exp(-a * abs(k))
return tanh(a/2.0) * exp(-a * abs(k))
def _cdf(self, x, a):
k = floor(x)
f = lambda k, a: 1.0 - exp(-a * k) / (exp(a) + 1)
f2 = lambda k, a: exp(a * (k + 1)) / (exp(a) + 1)
f2 = lambda k, a: exp(a * (k+1)) / (exp(a) + 1)
return _lazywhere(k >= 0, (k, a), f=f, f2=f2)
def _ppf(self, q, a):
const = 1 + exp(a)
vals = ceil(np.where(q < 1.0 / (1 + exp(-a)), log(q * const) / a - 1,
-log((1 - q) * const) / a))
vals = ceil(np.where(q < 1.0 / (1 + exp(-a)), log(q*const) / a - 1,
-log((1-q) * const) / a))
vals1 = vals - 1
return np.where(self._cdf(vals1, a) >= q, vals1, vals)
def _stats(self, a):
ea = exp(a)
mu2 = 2. * ea / (ea - 1.) ** 2
mu4 = 2. * ea * (ea ** 2 + 10. * ea + 1.) / (ea - 1.) ** 4
return 0., mu2, 0., mu4 / mu2 ** 2 - 3.
mu2 = 2.*ea/(ea-1.)**2
mu4 = 2.*ea*(ea**2+10.*ea+1.) / (ea-1.)**4
return 0., mu2, 0., mu4/mu2**2 - 3.
def _entropy(self, a):
return a / sinh(a) - log(tanh(a / 2.0))
return a / sinh(a) - log(tanh(a/2.0))
dlaplace = dlaplace_gen(a=-np.inf,
name='dlaplace', longname='A discrete Laplacian')
class skellam_gen(rv_discrete):
"""A Skellam discrete random variable.
%(before_notes)s
@ -762,29 +747,35 @@ class skellam_gen(rv_discrete):
%(example)s
"""
def _rvs(self, mu1, mu2):
n = self._size
return mtrand.poisson(mu1, n) - mtrand.poisson(mu2, n)
def _pmf(self, x, mu1, mu2):
px = np.where(x < 0,
_ncx2_pdf(2 * mu2, 2 * (1 - x), 2 * mu1) * 2,
_ncx2_pdf(2 * mu1, 2 * (1 + x), 2 * mu2) * 2)
_ncx2_pdf(2*mu2, 2*(1-x), 2*mu1)*2,
_ncx2_pdf(2*mu1, 2*(1+x), 2*mu2)*2)
# ncx2.pdf() returns nan's for extremely low probabilities
return px
def _cdf(self, x, mu1, mu2):
x = floor(x)
px = np.where(x < 0,
_ncx2_cdf(2 * mu2, -2 * x, 2 * mu1),
1 - _ncx2_cdf(2 * mu1, 2 * (x + 1), 2 * mu2))
_ncx2_cdf(2*mu2, -2*x, 2*mu1),
1-_ncx2_cdf(2*mu1, 2*(x+1), 2*mu2))
return px
def _stats(self, mu1, mu2):
mean = mu1 - mu2
var = mu1 + mu2
g1 = mean / sqrt((var) ** 3)
g1 = mean / sqrt((var)**3)
g2 = 1 / var
return mean, var, g1, g2
skellam = skellam_gen(a=-np.inf, name="skellam", longname='A Skellam')
# Collect names of classes and objects in this module.
pairs = list(globals().items())
_distn_names, _distn_gen_names = get_distribution_names(pairs, rv_discrete)
__all__ = _distn_names + _distn_gen_names

@ -12,9 +12,11 @@ import re
import inspect
import types
import warnings
from scipy.misc import doccer
from ._distr_params import distcont, distdiscrete
from scipy.special import xlogy, chndtr, gammaln, hyp0f1
from scipy.special import xlogy, chndtr, gammaln, hyp0f1, comb
# for root finding for discrete distribution ppf, and max likelihood estimation
from scipy import optimize
@ -23,11 +25,11 @@ from scipy import optimize
from scipy import integrate
# to approximate the pdf of a continuous distribution given its cdf
from scipy.misc import comb, derivative # @UnresolvedImport
from scipy.misc import derivative
from numpy import (arange, putmask, ravel, take, ones, sum, shape,
product, reshape, zeros, floor, logical_and, log, sqrt, exp,
ndarray, newaxis)
ndarray)
from numpy import (place, any, argsort, argmax, vectorize,
asarray, nan, inf, isinf, NINF, empty)
@ -55,91 +57,91 @@ docheaders = {'methods': """\nMethods\n-------\n""",
'examples': """\nExamples\n--------\n"""}
_doc_rvs = """\
rvs(%(shapes)s, loc=0, scale=1, size=1)
``rvs(%(shapes)s, loc=0, scale=1, size=1)``
Random variates.
"""
_doc_pdf = """\
pdf(x, %(shapes)s, loc=0, scale=1)
``pdf(x, %(shapes)s, loc=0, scale=1)``
Probability density function.
"""
_doc_logpdf = """\
logpdf(x, %(shapes)s, loc=0, scale=1)
``logpdf(x, %(shapes)s, loc=0, scale=1)``
Log of the probability density function.
"""
_doc_pmf = """\
pmf(x, %(shapes)s, loc=0, scale=1)
``pmf(x, %(shapes)s, loc=0, scale=1)``
Probability mass function.
"""
_doc_logpmf = """\
logpmf(x, %(shapes)s, loc=0, scale=1)
``logpmf(x, %(shapes)s, loc=0, scale=1)``
Log of the probability mass function.
"""
_doc_cdf = """\
cdf(x, %(shapes)s, loc=0, scale=1)
``cdf(x, %(shapes)s, loc=0, scale=1)``
Cumulative density function.
"""
_doc_logcdf = """\
logcdf(x, %(shapes)s, loc=0, scale=1)
``logcdf(x, %(shapes)s, loc=0, scale=1)``
Log of the cumulative density function.
"""
_doc_sf = """\
sf(x, %(shapes)s, loc=0, scale=1)
``sf(x, %(shapes)s, loc=0, scale=1)``
Survival function (1-cdf --- sometimes more accurate).
"""
_doc_logsf = """\
logsf(x, %(shapes)s, loc=0, scale=1)
``logsf(x, %(shapes)s, loc=0, scale=1)``
Log of the survival function.
"""
_doc_ppf = """\
ppf(q, %(shapes)s, loc=0, scale=1)
``ppf(q, %(shapes)s, loc=0, scale=1)``
Percent point function (inverse of cdf --- percentiles).
"""
_doc_isf = """\
isf(q, %(shapes)s, loc=0, scale=1)
``isf(q, %(shapes)s, loc=0, scale=1)``
Inverse survival function (inverse of sf).
"""
_doc_moment = """\
moment(n, %(shapes)s, loc=0, scale=1)
``moment(n, %(shapes)s, loc=0, scale=1)``
Non-central moment of order n
"""
_doc_stats = """\
stats(%(shapes)s, loc=0, scale=1, moments='mv')
``stats(%(shapes)s, loc=0, scale=1, moments='mv')``
Mean('m'), variance('v'), skew('s'), and/or kurtosis('k').
"""
_doc_entropy = """\
entropy(%(shapes)s, loc=0, scale=1)
``entropy(%(shapes)s, loc=0, scale=1)``
(Differential) entropy of the RV.
"""
_doc_fit = """\
fit(data, %(shapes)s, loc=0, scale=1)
``fit(data, %(shapes)s, loc=0, scale=1)``
Parameter estimates for generic data.
"""
_doc_expect = """\
expect(func, %(shapes)s, loc=0, scale=1, lb=None, ub=None, conditional=False, **kwds)
``expect(func, %(shapes)s, loc=0, scale=1, lb=None, ub=None, conditional=False, **kwds)``
Expected value of a function (of one argument) with respect to the distribution.
"""
_doc_expect_discrete = """\
expect(func, %(shapes)s, loc=0, lb=None, ub=None, conditional=False)
``expect(func, %(shapes)s, loc=0, lb=None, ub=None, conditional=False)``
Expected value of a function (of one argument) with respect to the distribution.
"""
_doc_median = """\
median(%(shapes)s, loc=0, scale=1)
``median(%(shapes)s, loc=0, scale=1)``
Median of the distribution.
"""
_doc_mean = """\
mean(%(shapes)s, loc=0, scale=1)
``mean(%(shapes)s, loc=0, scale=1)``
Mean of the distribution.
"""
_doc_var = """\
var(%(shapes)s, loc=0, scale=1)
``var(%(shapes)s, loc=0, scale=1)``
Variance of the distribution.
"""
_doc_std = """\
std(%(shapes)s, loc=0, scale=1)
``std(%(shapes)s, loc=0, scale=1)``
Standard deviation of the distribution.
"""
_doc_interval = """\
interval(alpha, %(shapes)s, loc=0, scale=1)
``interval(alpha, %(shapes)s, loc=0, scale=1)``
Endpoints of the range that contains alpha percent of the distribution
"""
_doc_allmethods = ''.join([docheaders['methods'], _doc_rvs, _doc_pdf,
@ -151,7 +153,7 @@ _doc_allmethods = ''.join([docheaders['methods'], _doc_rvs, _doc_pdf,
# Note that the two lines for %(shapes) are searched for and replaced in
# rv_continuous and rv_discrete - update there if the exact string changes
_doc_default_callparams = """\
_doc_default_callparams = """
Parameters
----------
x : array_like
@ -169,7 +171,8 @@ size : int or tuple of ints, optional
moments : str, optional
composed of letters ['mvsk'] specifying which moments to compute where
'm' = mean, 'v' = variance, 's' = (Fisher's) skew and
'k' = (Fisher's) kurtosis. (default='mv')
'k' = (Fisher's) kurtosis.
Default is 'mv'.
"""
_doc_default_longsummary = """\
Continuous random variables are defined from a standard form and may
@ -188,27 +191,42 @@ rv = %(name)s(%(shapes)s, loc=0, scale=1)
_doc_default_example = """\
Examples
--------
>>> import matplotlib.pyplot as plt
>>> from wafo.stats import %(name)s
>>> numargs = %(name)s.numargs
>>> [ %(shapes)s ] = [0.9,] * numargs
>>> rv = %(name)s(%(shapes)s)
>>> import matplotlib.pyplot as plt
>>> fig, ax = plt.subplots(1, 1)
Display frozen pdf
Calculate a few first moments:
>>> x = np.linspace(0, np.minimum(rv.dist.b, 3))
>>> h = plt.plot(x, rv.pdf(x))
%(set_vals_stmt)s
>>> mean, var, skew, kurt = %(name)s.stats(%(shapes)s, moments='mvsk')
Here, ``rv.dist.b`` is the right endpoint of the support of ``rv.dist``.
Display the probability density function (``pdf``):
Check accuracy of cdf and ppf
>>> x = np.linspace(%(name)s.ppf(0.01, %(shapes)s),
... %(name)s.ppf(0.99, %(shapes)s), 100)
>>> ax.plot(x, %(name)s.pdf(x, %(shapes)s),
... 'r-', lw=5, alpha=0.6, label='%(name)s pdf')
>>> prb = %(name)s.cdf(x, %(shapes)s)
>>> h = plt.semilogy(np.abs(x - %(name)s.ppf(prb, %(shapes)s)) + 1e-20)
Alternatively, freeze the distribution and display the frozen pdf:
>>> rv = %(name)s(%(shapes)s)
>>> ax.plot(x, rv.pdf(x), 'k-', lw=2, label='frozen pdf')
Random number generation
Check accuracy of ``cdf`` and ``ppf``:
>>> R = %(name)s.rvs(%(shapes)s, size=100)
>>> vals = %(name)s.ppf([0.001, 0.5, 0.999], %(shapes)s)
>>> np.allclose([0.001, 0.5, 0.999], %(name)s.cdf(vals, %(shapes)s))
True
Generate random numbers:
>>> r = %(name)s.rvs(%(shapes)s, size=1000)
And compare the histogram:
>>> ax.hist(r, normed=True, histtype='stepfilled', alpha=0.2)
>>> ax.legend(loc='best', frameon=False)
>>> plt.show()
Compare ML and MPS method
>>> phat = %(name)s.fit2(R, method='ml');
@ -301,26 +319,39 @@ docdict_discrete['frozennote'] = _doc_default_frozen_note
_doc_default_discrete_example = """\
Examples
--------
>>> from scipy.stats import %(name)s
>>> [ %(shapes)s ] = [<Replace with reasonable values>]
>>> rv = %(name)s(%(shapes)s)
>>> from wafo.stats import %(name)s
>>> import matplotlib.pyplot as plt
>>> fig, ax = plt.subplots(1, 1)
Display frozen pmf
Calculate a few first moments:
>>> x = np.arange(0, np.minimum(rv.dist.b, 3))
>>> h = plt.vlines(x, 0, rv.pmf(x), lw=2)
%(set_vals_stmt)s
>>> mean, var, skew, kurt = %(name)s.stats(%(shapes)s, moments='mvsk')
Here, ``rv.dist.b`` is the right endpoint of the support of ``rv.dist``.
Display the probability mass function (``pmf``):
Check accuracy of cdf and ppf
>>> x = np.arange(%(name)s.ppf(0.01, %(shapes)s),
... %(name)s.ppf(0.99, %(shapes)s))
>>> ax.plot(x, %(name)s.pmf(x, %(shapes)s), 'bo', ms=8, label='%(name)s pmf')
>>> ax.vlines(x, 0, %(name)s.pmf(x, %(shapes)s), colors='b', lw=5, alpha=0.5)
>>> prb = %(name)s.cdf(x, %(shapes)s)
>>> h = plt.semilogy(np.abs(x - %(name)s.ppf(prb, %(shapes)s)) + 1e-20)
Alternatively, freeze the distribution and display the frozen ``pmf``:
Random number generation
>>> rv = %(name)s(%(shapes)s)
>>> ax.vlines(x, 0, rv.pmf(x), colors='k', linestyles='-', lw=1,
... label='frozen pmf')
>>> ax.legend(loc='best', frameon=False)
>>> plt.show()
Check accuracy of ``cdf`` and ``ppf``:
>>> R = %(name)s.rvs(%(shapes)s, size=100)
>>> prob = %(name)s.cdf(x, %(shapes)s)
>>> np.allclose(x, %(name)s.ppf(prob, %(shapes)s))
True
Generate random numbers:
>>> r = %(name)s.rvs(%(shapes)s, size=1000)
"""
docdict_discrete['example'] = _doc_default_discrete_example
@ -408,6 +439,82 @@ def _kurtosis(data):
return m4 / m2**2 - 3
# Frozen RV class
class rv_frozen_old(object):
def __init__(self, dist, *args, **kwds):
self.args = args
self.kwds = kwds
# create a new instance
self.dist = dist.__class__(**dist._ctor_param)
# a, b may be set in _argcheck, depending on *args, **kwds. Ouch.
shapes, _, _ = self.dist._parse_args(*args, **kwds)
self.dist._argcheck(*shapes)
def pdf(self, x): # raises AttributeError in frozen discrete distribution
return self.dist.pdf(x, *self.args, **self.kwds)
def logpdf(self, x):
return self.dist.logpdf(x, *self.args, **self.kwds)
def cdf(self, x):
return self.dist.cdf(x, *self.args, **self.kwds)
def logcdf(self, x):
return self.dist.logcdf(x, *self.args, **self.kwds)
def ppf(self, q):
return self.dist.ppf(q, *self.args, **self.kwds)
def isf(self, q):
return self.dist.isf(q, *self.args, **self.kwds)
def rvs(self, size=None):
kwds = self.kwds.copy()
kwds.update({'size': size})
return self.dist.rvs(*self.args, **kwds)
def sf(self, x):
return self.dist.sf(x, *self.args, **self.kwds)
def logsf(self, x):
return self.dist.logsf(x, *self.args, **self.kwds)
def stats(self, moments='mv'):
kwds = self.kwds.copy()
kwds.update({'moments': moments})
return self.dist.stats(*self.args, **kwds)
def median(self):
return self.dist.median(*self.args, **self.kwds)
def mean(self):
return self.dist.mean(*self.args, **self.kwds)
def var(self):
return self.dist.var(*self.args, **self.kwds)
def std(self):
return self.dist.std(*self.args, **self.kwds)
def moment(self, n):
return self.dist.moment(n, *self.args, **self.kwds)
def entropy(self):
return self.dist.entropy(*self.args, **self.kwds)
def pmf(self, k):
return self.dist.pmf(k, *self.args, **self.kwds)
def logpmf(self, k):
return self.dist.logpmf(k, *self.args, **self.kwds)
def interval(self, alpha):
return self.dist.interval(alpha, *self.args, **self.kwds)
# Frozen RV class
class rv_frozen(object):
''' Frozen continous or discrete 1D Random Variable object (RV)
@ -528,74 +635,6 @@ class rv_frozen(object):
return self.dist.interval(alpha, *self.par)
# Frozen RV class
class rv_frozen_old(object):
def __init__(self, dist, *args, **kwds):
self.args = args
self.kwds = kwds
self.dist = dist
def pdf(self, x): # raises AttributeError in frozen discrete distribution
return self.dist.pdf(x, *self.args, **self.kwds)
def logpdf(self, x):
return self.dist.logpdf(x, *self.args, **self.kwds)
def cdf(self, x):
return self.dist.cdf(x, *self.args, **self.kwds)
def logcdf(self, x):
return self.dist.logcdf(x, *self.args, **self.kwds)
def ppf(self, q):
return self.dist.ppf(q, *self.args, **self.kwds)
def isf(self, q):
return self.dist.isf(q, *self.args, **self.kwds)
def rvs(self, size=None):
kwds = self.kwds.copy()
kwds.update({'size': size})
return self.dist.rvs(*self.args, **kwds)
def sf(self, x):
return self.dist.sf(x, *self.args, **self.kwds)
def logsf(self, x):
return self.dist.logsf(x, *self.args, **self.kwds)
def stats(self, moments='mv'):
kwds = self.kwds.copy()
kwds.update({'moments': moments})
return self.dist.stats(*self.args, **kwds)
def median(self):
return self.dist.median(*self.args, **self.kwds)
def mean(self):
return self.dist.mean(*self.args, **self.kwds)
def var(self):
return self.dist.var(*self.args, **self.kwds)
def std(self):
return self.dist.std(*self.args, **self.kwds)
def moment(self, n):
return self.dist.moment(n, *self.args, **self.kwds)
def entropy(self):
return self.dist.entropy(*self.args, **self.kwds)
def pmf(self, k):
return self.dist.pmf(k, *self.args, **self.kwds)
def logpmf(self, k):
return self.dist.logpmf(k, *self.args, **self.kwds)
def interval(self, alpha):
return self.dist.interval(alpha, *self.args, **self.kwds)
def valarray(shape, value=nan, typecode=None):
"""Return an array of all value.
@ -693,9 +732,11 @@ def _ncx2_log_pdf(x, df, nc):
fac = -nc/2.0 - x/2.0 + (a-1)*log(x) - a*log(2) - gammaln(a)
return fac + np.nan_to_num(log(hyp0f1(a, nc * x/4.0)))
def _ncx2_pdf(x, df, nc):
return np.exp(_ncx2_log_pdf(x, df, nc))
def _ncx2_cdf(x, df, nc):
return chndtr(x, df, nc)
@ -713,7 +754,8 @@ class rv_generic(object):
self._stats_has_moments = ((sign[2] is not None) or
('moments' in sign[0]))
def _construct_argparser(self, meths_to_inspect, locscale_in, locscale_out):
def _construct_argparser(
self, meths_to_inspect, locscale_in, locscale_out):
"""Construct the parser for the shape arguments.
Generates the argument-parsing functions dynamically and attaches
@ -789,6 +831,36 @@ class rv_generic(object):
# allows more general subclassing with *args
self.numargs = len(shapes)
def _construct_doc(self, docdict, shapes_vals=None):
"""Construct the instance docstring with string substitutions."""
tempdict = docdict.copy()
tempdict['name'] = self.name or 'distname'
tempdict['shapes'] = self.shapes or ''
if shapes_vals is None:
shapes_vals = ()
vals = ', '.join(str(_) for _ in shapes_vals)
tempdict['vals'] = vals
if self.shapes:
tempdict['set_vals_stmt'] = '>>> %s = %s' % (self.shapes, vals)
else:
tempdict['set_vals_stmt'] = ''
if self.shapes is None:
# remove shapes from call parameters if there are none
for item in ['callparams', 'default', 'before_notes']:
tempdict[item] = tempdict[item].replace(
"\n%(shapes)s : array_like\n shape parameters", "")
for i in range(2):
if self.shapes is None:
# necessary because we use %(shapes)s in two forms (w w/o ", ")
self.__doc__ = self.__doc__.replace("%(shapes)s, ", "")
self.__doc__ = doccer.docformat(self.__doc__, tempdict)
# correct for empty shapes
self.__doc__ = self.__doc__.replace('(, ', '(').replace(', )', ')')
def freeze(self, *args, **kwds):
"""Freeze the distribution for the given arguments.
@ -1297,68 +1369,67 @@ class rv_continuous(rv_generic):
Methods
-------
rvs(<shape(s)>, loc=0, scale=1, size=1)
``rvs(<shape(s)>, loc=0, scale=1, size=1)``
random variates
pdf(x, <shape(s)>, loc=0, scale=1)
``pdf(x, <shape(s)>, loc=0, scale=1)``
probability density function
logpdf(x, <shape(s)>, loc=0, scale=1)
``logpdf(x, <shape(s)>, loc=0, scale=1)``
log of the probability density function
cdf(x, <shape(s)>, loc=0, scale=1)
``cdf(x, <shape(s)>, loc=0, scale=1)``
cumulative density function
logcdf(x, <shape(s)>, loc=0, scale=1)
``logcdf(x, <shape(s)>, loc=0, scale=1)``
log of the cumulative density function
sf(x, <shape(s)>, loc=0, scale=1)
``sf(x, <shape(s)>, loc=0, scale=1)``
survival function (1-cdf --- sometimes more accurate)
logsf(x, <shape(s)>, loc=0, scale=1)
``logsf(x, <shape(s)>, loc=0, scale=1)``
log of the survival function
ppf(q, <shape(s)>, loc=0, scale=1)
``ppf(q, <shape(s)>, loc=0, scale=1)``
percent point function (inverse of cdf --- quantiles)
isf(q, <shape(s)>, loc=0, scale=1)
``isf(q, <shape(s)>, loc=0, scale=1)``
inverse survival function (inverse of sf)
moment(n, <shape(s)>, loc=0, scale=1)
``moment(n, <shape(s)>, loc=0, scale=1)``
non-central n-th moment of the distribution. May not work for array
arguments.
stats(<shape(s)>, loc=0, scale=1, moments='mv')
``stats(<shape(s)>, loc=0, scale=1, moments='mv')``
mean('m'), variance('v'), skew('s'), and/or kurtosis('k')
entropy(<shape(s)>, loc=0, scale=1)
``entropy(<shape(s)>, loc=0, scale=1)``
(differential) entropy of the RV.
fit(data, <shape(s)>, loc=0, scale=1)
``fit(data, <shape(s)>, loc=0, scale=1)``
Parameter estimates for generic data
expect(func=None, args=(), loc=0, scale=1, lb=None, ub=None,
conditional=False, **kwds)
``expect(func=None, args=(), loc=0, scale=1, lb=None, ub=None, conditional=False, **kwds)``
Expected value of a function with respect to the distribution.
Additional kwd arguments passed to integrate.quad
median(<shape(s)>, loc=0, scale=1)
``median(<shape(s)>, loc=0, scale=1)``
Median of the distribution.
mean(<shape(s)>, loc=0, scale=1)
``mean(<shape(s)>, loc=0, scale=1)``
Mean of the distribution.
std(<shape(s)>, loc=0, scale=1)
``std(<shape(s)>, loc=0, scale=1)``
Standard deviation of the distribution.
var(<shape(s)>, loc=0, scale=1)
``var(<shape(s)>, loc=0, scale=1)``
Variance of the distribution.
interval(alpha, <shape(s)>, loc=0, scale=1)
``interval(alpha, <shape(s)>, loc=0, scale=1)``
Interval that with `alpha` percent probability contains a random
realization of this distribution.
__call__(<shape(s)>, loc=0, scale=1)
``__call__(<shape(s)>, loc=0, scale=1)``
Calling a distribution instance creates a frozen RV object with the
same methods but holding the given shape, location, and scale fixed.
See Notes section.
@ -1469,6 +1540,12 @@ class rv_continuous(rv_generic):
super(rv_continuous, self).__init__()
# save the ctor parameters, cf generic freeze
self._ctor_param = dict(
momtype=momtype, a=a, b=b, xtol=xtol,
badvalue=badvalue, name=name, longname=longname,
shapes=shapes, extradoc=extradoc)
if badvalue is None:
badvalue = nan
if name is None:
@ -1483,11 +1560,7 @@ class rv_continuous(rv_generic):
self.b = inf
self.xtol = xtol
self._size = 1
self.m = 0.0
self.moment_type = momtype
self.expandarr = 1
self.shapes = shapes
self._construct_argparser(meths_to_inspect=[self._pdf, self._cdf],
locscale_in='loc=0, scale=1',
@ -1497,13 +1570,13 @@ class rv_continuous(rv_generic):
self._ppfvec = vectorize(self._ppf_single, otypes='d')
self._ppfvec.nin = self.numargs + 1
self.vecentropy = vectorize(self._entropy, otypes='d')
self.vecentropy.nin = self.numargs + 1
self._cdfvec = vectorize(self._cdf_single, otypes='d')
self._cdfvec.nin = self.numargs + 1
# backwards compatibility
self.vecfunc = self._ppfvec
self.veccdf = self._cdfvec
# backwards compat. these were removed in 0.14.0, put back but
# deprecated in 0.14.1:
self.vecfunc = np.deprecate(self._ppfvec, "vecfunc")
self.veccdf = np.deprecate(self._cdfvec, "veccdf")
self.extradoc = extradoc
if momtype == 0:
@ -1527,7 +1600,8 @@ class rv_continuous(rv_generic):
self._construct_default_doc(longname=longname,
extradoc=extradoc)
else:
self._construct_doc()
dct = dict(distcont)
self._construct_doc(docdict, dct.get(self.name))
def _construct_default_doc(self, longname=None, extradoc=None):
"""Construct instance docstring from the default template."""
@ -1540,24 +1614,7 @@ class rv_continuous(rv_generic):
self.__doc__ = ''.join(['%s continuous random variable.' % longname,
'\n\n%(before_notes)s\n', docheaders['notes'],
extradoc, '\n%(example)s'])
self._construct_doc()
def _construct_doc(self):
"""Construct the instance docstring with string substitutions."""
tempdict = docdict.copy()
tempdict['name'] = self.name or 'distname'
tempdict['shapes'] = self.shapes or ''
if self.shapes is None:
# remove shapes from call parameters if there are none
for item in ['callparams', 'default', 'before_notes']:
tempdict[item] = tempdict[item].replace(
"\n%(shapes)s : array_like\n shape parameters", "")
for _i in range(2):
if self.shapes is None:
# necessary because we use %(shapes)s in two forms (w w/o ", ")
self.__doc__ = self.__doc__.replace("%(shapes)s, ", "")
self.__doc__ = doccer.docformat(self.__doc__, tempdict)
self._construct_doc(docdict)
def _ppf_to_solve(self, x, q, *args):
return self.cdf(*(x, )+args)-q
@ -2162,7 +2219,7 @@ class rv_continuous(rv_generic):
# logDj = log((yU-yL)/(r-1)) for j = i+1,i+2,...i+r-1
# The following is OK when only minimization of T is wanted
i_tie = np.nonzero(tie)
i_tie, = np.nonzero(tie)
tiedata = x[i_tie]
logD[i_tie + 1] = log(self._pdf(tiedata, *args)) - log(scale)
@ -2265,7 +2322,8 @@ class rv_continuous(rv_generic):
restore = None
else:
if len(fixedn) == len(index):
raise ValueError("All parameters fixed. There is nothing to optimize.")
raise ValueError(
"All parameters fixed. There is nothing to optimize.")
def restore(args, theta):
# Replace with theta for all numbers not in fixedn
@ -2462,15 +2520,15 @@ class rv_continuous(rv_generic):
def _entropy(self, *args):
def integ(x):
val = self._pdf(x, *args)
return xlogy(val, val)
return -xlogy(val, val)
# upper limit is often inf, so suppress warnings when integrating
olderr = np.seterr(over='ignore')
entr = -integrate.quad(integ, self.a, self.b)[0]
h = integrate.quad(integ, self.a, self.b)[0]
np.seterr(**olderr)
if not np.isnan(entr):
return entr
if not np.isnan(h):
return h
else:
# try with different limits if integration problems
low, upp = self.ppf([1e-10, 1. - 1e-10], *args)
@ -2482,7 +2540,7 @@ class rv_continuous(rv_generic):
lower = low
else:
lower = self.a
return -integrate.quad(integ, lower, upper)[0]
return integrate.quad(integ, lower, upper)[0]
def entropy(self, *args, **kwds):
"""
@ -2606,12 +2664,12 @@ def _drv_nonzero(self, k, *args):
def _drv_moment(self, n, *args):
n = asarray(n)
return sum(self.xk**n[newaxis, ...] * self.pk, axis=0)
return sum(self.xk**n[np.newaxis, ...] * self.pk, axis=0)
def _drv_moment_gen(self, t, *args):
t = asarray(t)
return sum(exp(self.xk * t[newaxis, ...]) * self.pk, axis=0)
return sum(exp(self.xk * t[np.newaxis, ...]) * self.pk, axis=0)
def _drv2_moment(self, n, *args):
@ -2716,8 +2774,7 @@ def entropy(pk, qk=None, base=None):
If only probabilities `pk` are given, the entropy is calculated as
``S = -sum(pk * log(pk), axis=0)``.
If `qk` is not None, then compute a relative entropy (also known as
Kullback-Leibler divergence or Kullback-Leibler distance)
If `qk` is not None, then compute the Kullback-Leibler divergence
``S = sum(pk * log(pk / qk), axis=0)``.
This routine will normalize `pk` and `qk` if they don't sum to 1.
@ -2809,65 +2866,64 @@ class rv_discrete(rv_generic):
Methods
-------
generic.rvs(<shape(s)>, loc=0, size=1)
``generic.rvs(<shape(s)>, loc=0, size=1)``
random variates
generic.pmf(x, <shape(s)>, loc=0)
``generic.pmf(x, <shape(s)>, loc=0)``
probability mass function
logpmf(x, <shape(s)>, loc=0)
``logpmf(x, <shape(s)>, loc=0)``
log of the probability density function
generic.cdf(x, <shape(s)>, loc=0)
``generic.cdf(x, <shape(s)>, loc=0)``
cumulative density function
generic.logcdf(x, <shape(s)>, loc=0)
``generic.logcdf(x, <shape(s)>, loc=0)``
log of the cumulative density function
generic.sf(x, <shape(s)>, loc=0)
``generic.sf(x, <shape(s)>, loc=0)``
survival function (1-cdf --- sometimes more accurate)
generic.logsf(x, <shape(s)>, loc=0, scale=1)
``generic.logsf(x, <shape(s)>, loc=0, scale=1)``
log of the survival function
generic.ppf(q, <shape(s)>, loc=0)
``generic.ppf(q, <shape(s)>, loc=0)``
percent point function (inverse of cdf --- percentiles)
generic.isf(q, <shape(s)>, loc=0)
``generic.isf(q, <shape(s)>, loc=0)``
inverse survival function (inverse of sf)
generic.moment(n, <shape(s)>, loc=0)
``generic.moment(n, <shape(s)>, loc=0)``
non-central n-th moment of the distribution. May not work for array
arguments.
generic.stats(<shape(s)>, loc=0, moments='mv')
``generic.stats(<shape(s)>, loc=0, moments='mv')``
mean('m', axis=0), variance('v'), skew('s'), and/or kurtosis('k')
generic.entropy(<shape(s)>, loc=0)
``generic.entropy(<shape(s)>, loc=0)``
entropy of the RV
generic.expect(func=None, args=(), loc=0, lb=None, ub=None,
conditional=False)
``generic.expect(func=None, args=(), loc=0, lb=None, ub=None, conditional=False)``
Expected value of a function with respect to the distribution.
Additional kwd arguments passed to integrate.quad
generic.median(<shape(s)>, loc=0)
``generic.median(<shape(s)>, loc=0)``
Median of the distribution.
generic.mean(<shape(s)>, loc=0)
``generic.mean(<shape(s)>, loc=0)``
Mean of the distribution.
generic.std(<shape(s)>, loc=0)
``generic.std(<shape(s)>, loc=0)``
Standard deviation of the distribution.
generic.var(<shape(s)>, loc=0)
``generic.var(<shape(s)>, loc=0)``
Variance of the distribution.
generic.interval(alpha, <shape(s)>, loc=0)
``generic.interval(alpha, <shape(s)>, loc=0)``
Interval that with `alpha` percent probability contains a random
realization of this distribution.
generic(<shape(s)>, loc=0)
``generic(<shape(s)>, loc=0)``
calling a distribution instance returns a frozen distribution
Notes
@ -2881,7 +2937,7 @@ class rv_discrete(rv_generic):
To create a new discrete distribution, we would do the following::
class poisson_gen(rv_discrete):
#"Poisson distribution"
# "Poisson distribution"
def _pmf(self, k, mu):
...
@ -2911,32 +2967,25 @@ class rv_discrete(rv_generic):
Custom made discrete distribution:
>>> import matplotlib.pyplot as plt
>>> from scipy import stats
>>> xk = np.arange(7)
>>> pk = (0.1, 0.2, 0.3, 0.1, 0.1, 0.1, 0.1)
>>> pk = (0.1, 0.2, 0.3, 0.1, 0.1, 0.0, 0.2)
>>> custm = stats.rv_discrete(name='custm', values=(xk, pk))
>>> h = plt.plot(xk, custm.pmf(xk))
>>>
>>> import matplotlib.pyplot as plt
>>> fig, ax = plt.subplots(1, 1)
>>> ax.plot(xk, custm.pmf(xk), 'ro', ms=12, mec='r')
>>> ax.vlines(xk, 0, custm.pmf(xk), colors='r', lw=4)
>>> plt.show()
Random number generation:
>>> R = custm.rvs(size=100)
Display frozen pmf:
>>> numargs = generic.numargs
>>> [ <shape(s)> ] = ['Replace with resonable value', ]*numargs
>>> rv = generic(<shape(s)>)
>>> x = np.arange(0, np.min(rv.dist.b, 3)+1)
>>> h = plt.plot(x, rv.pmf(x))
Here, ``rv.dist.b`` is the right endpoint of the support of ``rv.dist``.
Check accuracy of cdf and ppf:
>>> prb = generic.cdf(x, <shape(s)>)
>>> h = plt.semilogy(np.abs(x-generic.ppf(prb, <shape(s)>))+1e-20)
>>> prb = custm.cdf(x, <shape(s)>)
>>> h = plt.semilogy(np.abs(x-custm.ppf(prb, <shape(s)>))+1e-20)
"""
def __init__(self, a=0, b=inf, name=None, badvalue=None,
@ -2945,6 +2994,12 @@ class rv_discrete(rv_generic):
super(rv_discrete, self).__init__()
# cf generic freeze
self._ctor_param = dict(
a=a, b=b, name=name, badvalue=badvalue,
moment_tol=moment_tol, values=values, inc=inc,
longname=longname, shapes=shapes, extradoc=extradoc)
if badvalue is None:
badvalue = nan
if name is None:
@ -3001,9 +3056,11 @@ class rv_discrete(rv_generic):
_vec_generic_moment.nin = self.numargs + 2
self.generic_moment = instancemethod(_vec_generic_moment,
self, rv_discrete)
# backwards compatibility
self.vec_generic_moment = _vec_generic_moment
# backwards compat. was removed in 0.14.0, put back but
# deprecated in 0.14.1:
self.vec_generic_moment = np.deprecate(_vec_generic_moment,
"vec_generic_moment",
"generic_moment")
# correct nin for ppf vectorization
_vppf = vectorize(_drv2_ppfsingle, otypes='d')
@ -3028,7 +3085,8 @@ class rv_discrete(rv_generic):
self._construct_default_doc(longname=longname,
extradoc=extradoc)
else:
self._construct_doc()
dct = dict(distdiscrete)
self._construct_doc(docdict_discrete, dct.get(self.name))
#discrete RV do not have the scale parameter, remove it
self.__doc__ = self.__doc__.replace(
@ -3044,24 +3102,7 @@ class rv_discrete(rv_generic):
self.__doc__ = ''.join(['%s discrete random variable.' % longname,
'\n\n%(before_notes)s\n', docheaders['notes'],
extradoc, '\n%(example)s'])
self._construct_doc()
def _construct_doc(self):
"""Construct the instance docstring with string substitutions."""
tempdict = docdict_discrete.copy()
tempdict['name'] = self.name or 'distname'
tempdict['shapes'] = self.shapes or ''
if self.shapes is None:
# remove shapes from call parameters if there are none
for item in ['callparams', 'default', 'before_notes']:
tempdict[item] = tempdict[item].replace(
"\n%(shapes)s : array_like\n shape parameters", "")
for _i in range(2):
if self.shapes is None:
# necessary because we use %(shapes)s in two forms (w w/o ", ")
self.__doc__ = self.__doc__.replace("%(shapes)s, ", "")
self.__doc__ = doccer.docformat(self.__doc__, tempdict)
self._construct_doc(docdict_discrete)
def _nonzero(self, k, *args):
return floor(k) == k
@ -3137,7 +3178,7 @@ class rv_discrete(rv_generic):
place(output, (1-cond0) + np.isnan(k), self.badvalue)
if any(cond):
goodargs = argsreduce(cond, *((k,)+args))
place(output, cond, self._pmf(*goodargs))
place(output, cond, np.clip(self._pmf(*goodargs), 0, 1))
if output.ndim == 0:
return output[()]
return output
@ -3213,7 +3254,7 @@ class rv_discrete(rv_generic):
if any(cond):
goodargs = argsreduce(cond, *((k,)+args))
place(output, cond, self._cdf(*goodargs))
place(output, cond, np.clip(self._cdf(*goodargs), 0, 1))
if output.ndim == 0:
return output[()]
return output
@ -3291,7 +3332,7 @@ class rv_discrete(rv_generic):
place(output, cond2, 1.0)
if any(cond):
goodargs = argsreduce(cond, *((k,)+args))
place(output, cond, self._sf(*goodargs))
place(output, cond, np.clip(self._sf(*goodargs), 0, 1))
if output.ndim == 0:
return output[()]
return output
@ -3382,7 +3423,7 @@ class rv_discrete(rv_generic):
def isf(self, q, *args, **kwds):
"""
Inverse survival function (1-sf) at q of the given RV.
Inverse survival function (inverse of `sf`) at q of the given RV.
Parameters
----------
@ -3555,3 +3596,36 @@ class rv_discrete(rv_generic):
if count > maxcount:
warnings.warn('expect(): sum did not converge', RuntimeWarning)
return tot/invfac
def get_distribution_names(namespace_pairs, rv_base_class):
"""
Collect names of statistical distributions and their generators.
Parameters
----------
namespace_pairs : sequence
A snapshot of (name, value) pairs in the namespace of a module.
rv_base_class : class
The base class of random variable generator classes in a module.
Returns
-------
distn_names : list of strings
Names of the statistical distributions.
distn_gen_names : list of strings
Names of the generators of the statistical distributions.
Note that these are not simply the names of the statistical
distributions, with a _gen suffix added.
"""
distn_names = []
distn_gen_names = []
for name, value in namespace_pairs:
if name.startswith('_'):
continue
if name.endswith('_gen') and issubclass(value, rv_base_class):
distn_gen_names.append(name)
if isinstance(value, rv_base_class):
distn_names.append(name)
return distn_names, distn_gen_names

@ -0,0 +1,116 @@
"""
Sane parameters for stats.distributions.
"""
distcont = [
['alpha', (3.5704770516650459,)],
['anglit', ()],
['arcsine', ()],
['beta', (2.3098496451481823, 0.62687954300963677)],
['betaprime', (5, 6)],
['bradford', (0.29891359763170633,)],
['burr', (10.5, 4.3)],
['cauchy', ()],
['chi', (78,)],
['chi2', (55,)],
['cosine', ()],
['dgamma', (1.1023326088288166,)],
['dweibull', (2.0685080649914673,)],
['erlang', (10,)],
['expon', ()],
['exponpow', (2.697119160358469,)],
['exponweib', (2.8923945291034436, 1.9505288745913174)],
['f', (29, 18)],
['fatiguelife', (29,)], # correction numargs = 1
['fisk', (3.0857548622253179,)],
['foldcauchy', (4.7164673455831894,)],
['foldnorm', (1.9521253373555869,)],
['frechet_l', (3.6279911255583239,)],
['frechet_r', (1.8928171603534227,)],
['gamma', (1.9932305483800778,)],
['gausshyper', (13.763771604130699, 3.1189636648681431,
2.5145980350183019, 5.1811649903971615)], # veryslow
['genexpon', (9.1325976465418908, 16.231956600590632, 3.2819552690843983)],
['genextreme', (-0.1,)],
['gengamma', (4.4162385429431925, 3.1193091679242761)],
['genhalflogistic', (0.77274727809929322,)],
['genlogistic', (0.41192440799679475,)],
['genpareto', (0.1,)], # use case with finite moments
['gilbrat', ()],
['gompertz', (0.94743713075105251,)],
['gumbel_l', ()],
['gumbel_r', ()],
['halfcauchy', ()],
['halflogistic', ()],
['halfnorm', ()],
['hypsecant', ()],
['invgamma', (4.0668996136993067,)],
['invgauss', (0.14546264555347513,)],
['invweibull', (10.58,)],
['johnsonsb', (4.3172675099141058, 3.1837781130785063)],
['johnsonsu', (2.554395574161155, 2.2482281679651965)],
['ksone', (1000,)], # replace 22 by 100 to avoid failing range, ticket 956
['kstwobign', ()],
['laplace', ()],
['levy', ()],
['levy_l', ()],
['levy_stable', (0.35667405469844993,
-0.67450531578494011)], # NotImplementedError
# rvs not tested
['loggamma', (0.41411931826052117,)],
['logistic', ()],
['loglaplace', (3.2505926592051435,)],
['lognorm', (0.95368226960575331,)],
['lomax', (1.8771398388773268,)],
['maxwell', ()],
['mielke', (10.4, 3.6)],
['nakagami', (4.9673794866666237,)],
['ncf', (27, 27, 0.41578441799226107)],
['nct', (14, 0.24045031331198066)],
['ncx2', (21, 1.0560465975116415)],
['norm', ()],
['pareto', (2.621716532144454,)],
['pearson3', (0.1,)],
['powerlaw', (1.6591133289905851,)],
['powerlognorm', (2.1413923530064087, 0.44639540782048337)],
['powernorm', (4.4453652254590779,)],
['rayleigh', ()],
['rdist', (0.9,)], # feels also slow
['recipinvgauss', (0.63004267809369119,)],
['reciprocal', (0.0062309367010521255, 1.0062309367010522)],
['rice', (0.7749725210111873,)],
['semicircular', ()],
['t', (2.7433514990818093,)],
['triang', (0.15785029824528218,)],
['truncexpon', (4.6907725456810478,)],
['truncnorm', (-1.0978730080013919, 2.7306754109031979)],
['truncnorm', (0.1, 2.)],
['tukeylambda', (3.1321477856738267,)],
['uniform', ()],
['vonmises', (3.9939042581071398,)],
['vonmises_line', (3.9939042581071398,)],
['wald', ()],
['weibull_max', (2.8687961709100187,)],
['weibull_min', (1.7866166930421596,)],
['wrapcauchy', (0.031071279018614728,)]]
distdiscrete = [
['bernoulli',(0.3,)],
['binom', (5, 0.4)],
['boltzmann',(1.4, 19)],
['dlaplace', (0.8,)], # 0.5
['geom', (0.5,)],
['hypergeom',(30, 12, 6)],
['hypergeom',(21,3,12)], # numpy.random (3,18,12) numpy ticket:921
['hypergeom',(21,18,11)], # numpy.random (18,3,11) numpy ticket:921
['logser', (0.6,)], # reenabled, numpy ticket:921
['nbinom', (5, 0.5)],
['nbinom', (0.4, 0.4)], # from tickets: 583
['planck', (0.51,)], # 4.1
['poisson', (0.6,)],
['randint', (7, 31)],
['skellam', (15, 8)],
['zipf', (6.5,)]
]

@ -3,13 +3,13 @@
#
from __future__ import division, print_function, absolute_import
from scipy.misc import doccer
from functools import wraps
import numpy as np
import scipy.linalg
from scipy.misc import doccer
from scipy.special import gammaln
__all__ = ['multivariate_normal']
__all__ = ['multivariate_normal', 'dirichlet']
_LOG_2PI = np.log(2 * np.pi)
@ -53,13 +53,22 @@ def _process_parameters(dim, mean, cov):
cov.shape = (1, 1)
if mean.ndim != 1 or mean.shape[0] != dim:
raise ValueError("Array 'mean' must be vector of length %d." % dim)
raise ValueError("Array 'mean' must be a vector of length %d." % dim)
if cov.ndim == 0:
cov = cov * np.eye(dim)
elif cov.ndim == 1:
cov = np.diag(cov)
elif cov.ndim == 2 and cov.shape != (dim, dim):
rows, cols = cov.shape
if rows != cols:
msg = ("Array 'cov' must be square if it is two dimensional,"
" but cov.shape = %s." % str(cov.shape))
else:
if cov.shape != (dim, dim):
msg = ("Dimension mismatch: array 'cov' is of shape %s,"
" but 'mean' is a vector of length %d.")
msg = msg % (str(cov.shape), len(mean))
raise ValueError(msg)
elif cov.ndim > 2:
raise ValueError("Array 'cov' must be at most two-dimensional,"
" but cov.ndim = %d" % cov.ndim)
@ -97,6 +106,41 @@ def _squeeze_output(out):
return out
def _eigvalsh_to_eps(spectrum, cond=None, rcond=None):
"""
Determine which eigenvalues are "small" given the spectrum.
This is for compatibility across various linear algebra functions
that should agree about whether or not a Hermitian matrix is numerically
singular and what is its numerical matrix rank.
This is designed to be compatible with scipy.linalg.pinvh.
Parameters
----------
spectrum : 1d ndarray
Array of eigenvalues of a Hermitian matrix.
cond, rcond : float, optional
Cutoff for small eigenvalues.
Singular values smaller than rcond * largest_eigenvalue are
considered zero.
If None or -1, suitable machine precision is used.
Returns
-------
eps : float
Magnitude cutoff for numerical negligibility.
"""
if rcond is not None:
cond = rcond
if cond in [None, -1]:
t = spectrum.dtype.char.lower()
factor = {'f': 1E3, 'd': 1E6}
cond = factor[t] * np.finfo(t).eps
eps = cond * np.max(abs(spectrum))
return eps
def _pinv_1d(v, eps=1e-5):
"""
A helper function for computing the pseudoinverse.
@ -106,7 +150,7 @@ def _pinv_1d(v, eps=1e-5):
v : iterable of numbers
This may be thought of as a vector of eigenvalues or singular values.
eps : float
Elements of v smaller than eps are considered negligible.
Values with magnitude no greater than eps are considered negligible.
Returns
-------
@ -114,97 +158,101 @@ def _pinv_1d(v, eps=1e-5):
A vector of pseudo-inverted numbers.
"""
return np.array([0 if abs(x) < eps else 1/x for x in v], dtype=float)
return np.array([0 if abs(x) <= eps else 1/x for x in v], dtype=float)
def _psd_pinv_decomposed_log_pdet(mat, cond=None, rcond=None,
lower=True, check_finite=True):
class _PSD(object):
"""
Compute a decomposition of the pseudo-inverse and the logarithm of
the pseudo-determinant of a symmetric positive semi-definite
matrix.
The pseudo-determinant of a matrix is defined as the product of
the non-zero eigenvalues, and coincides with the usual determinant
for a full matrix.
Compute coordinated functions of a symmetric positive semidefinite matrix.
This class addresses two issues. Firstly it allows the pseudoinverse,
the logarithm of the pseudo-determinant, and the rank of the matrix
to be computed using one call to eigh instead of three.
Secondly it allows these functions to be computed in a way
that gives mutually compatible results.
All of the functions are computed with a common understanding as to
which of the eigenvalues are to be considered negligibly small.
The functions are designed to coordinate with scipy.linalg.pinvh()
but not necessarily with np.linalg.det() or with np.linalg.matrix_rank().
Parameters
----------
mat : array_like
Input array of shape (`m`, `n`)
cond, rcond : float or None
Cutoff for 'small' singular values.
Eigenvalues smaller than ``rcond*largest_eigenvalue``
are considered zero.
M : 2d array-like
Symmetric positive semidefinite matrix.
cond, rcond : float, optional
Cutoff for small eigenvalues.
Singular values smaller than rcond * largest_eigenvalue are
considered zero.
If None or -1, suitable machine precision is used.
lower : bool, optional
Whether the pertinent array data is taken from the lower or upper
triangle of `mat`. (Default: lower)
check_finite : boolean, optional
Whether to check that the input matrix contains only finite numbers.
Disabling may give a performance gain, but may result in problems
(crashes, non-termination) if the inputs do contain infinities or NaNs.
Whether the pertinent array data is taken from the lower
or upper triangle of M. (Default: lower)
check_finite : bool, optional
Whether to check that the input matrices contain only finite
numbers. Disabling may give a performance gain, but may result
in problems (crashes, non-termination) if the inputs do contain
infinities or NaNs.
allow_singular : bool, optional
Whether to allow a singular matrix. (Default: True)
Returns
-------
M : array_like
The pseudo-inverse of the input matrix is np.dot(M, M.T).
log_pdet : float
Logarithm of the pseudo-determinant of the matrix.
Notes
-----
The arguments are similar to those of scipy.linalg.pinvh().
"""
# Compute the symmetric eigendecomposition.
# The input covariance matrix is required to be real symmetric
# and positive semidefinite which implies that its eigenvalues
# are all real and non-negative,
# but clip them anyway to avoid numerical issues.
# TODO: the code to set cond/rcond is identical to that in
# scipy.linalg.{pinvh, pinv2} and if/when this function is subsumed
# into scipy.linalg it should probably be shared between all of
# these routines.
def __init__(self, M, cond=None, rcond=None, lower=True,
check_finite=True, allow_singular=True):
# Compute the symmetric eigendecomposition.
# Note that eigh takes care of array conversion, chkfinite,
# and assertion that the matrix is square.
s, u = scipy.linalg.eigh(mat, lower=lower, check_finite=check_finite)
if rcond is not None:
cond = rcond
if cond in [None, -1]:
t = u.dtype.char.lower()
factor = {'f': 1E3, 'd': 1E6}
cond = factor[t] * np.finfo(t).eps
eps = cond * np.max(abs(s))
s, u = scipy.linalg.eigh(M, lower=lower, check_finite=check_finite)
eps = _eigvalsh_to_eps(s, cond, rcond)
if np.min(s) < -eps:
raise ValueError('the covariance matrix must be positive semidefinite')
raise ValueError('the input matrix must be positive semidefinite')
d = s[s > eps]
if len(d) < len(s) and not allow_singular:
raise np.linalg.LinAlgError('singular matrix')
s_pinv = _pinv_1d(s, eps)
U = np.multiply(u, np.sqrt(s_pinv))
log_pdet = np.sum(np.log(s[s > eps]))
return U, log_pdet
# Initialize the eagerly precomputed attributes.
self.rank = len(d)
self.U = U
self.log_pdet = np.sum(np.log(d))
# Initialize an attribute to be lazily computed.
self._pinv = None
@property
def pinv(self):
if self._pinv is None:
self._pinv = np.dot(self.U, self.U.T)
return self._pinv
_doc_default_callparams = \
"""mean : array_like, optional
_doc_default_callparams = """\
mean : array_like, optional
Mean of the distribution (default zero)
cov : array_like, optional
Covariance matrix of the distribution (default one)
allow_singular : bool, optional
Whether to allow a singular covariance matrix. (Default: False)
"""
_doc_callparams_note = \
"""Setting the parameter `mean` to `None` is equivalent to having `mean`
be the zero-vector. The parameter `cov` can be a scalar, in which case
the covariance matrix is the identity times that value, a vector of
diagonal entries for the covariance matrix, or a two-dimensional
array_like.
"""
"""Setting the parameter `mean` to `None` is equivalent to having `mean`
be the zero-vector. The parameter `cov` can be a scalar, in which case
the covariance matrix is the identity times that value, a vector of
diagonal entries for the covariance matrix, or a two-dimensional
array_like.
"""
_doc_frozen_callparams = ""
_doc_frozen_callparams_note = \
"""See class definition for a detailed description of parameters."""
"""See class definition for a detailed description of parameters."""
docdict_params = {
'_doc_default_callparams': _doc_default_callparams,
@ -224,15 +272,13 @@ class multivariate_normal_gen(object):
The `mean` keyword specifies the mean. The `cov` keyword specifies the
covariance matrix.
.. versionadded:: 0.14.0
Methods
-------
pdf(x, mean=None, cov=1)
pdf(x, mean=None, cov=1, allow_singular=False)
Probability density function.
logpdf(x, mean=None, cov=1)
logpdf(x, mean=None, cov=1, allow_singular=False)
Log of the probability density function.
rvs(mean=None, cov=1)
rvs(mean=None, cov=1, allow_singular=False, size=1)
Draw random samples from a multivariate normal distribution.
entropy()
Compute the differential entropy of the multivariate normal.
@ -247,7 +293,7 @@ class multivariate_normal_gen(object):
and covariance parameters, returning a "frozen" multivariate normal
random variable:
rv = multivariate_normal(mean=None, scale=1)
rv = multivariate_normal(mean=None, cov=1, allow_singular=False)
- Frozen object with the same methods but holding the given
mean and covariance fixed.
@ -269,8 +315,11 @@ class multivariate_normal_gen(object):
where :math:`\mu` is the mean, :math:`\Sigma` the covariance matrix,
and :math:`k` is the dimension of the space where :math:`x` takes values.
.. versionadded:: 0.14.0
Examples
--------
>>> import matplotlib.pyplot as plt
>>> from scipy.stats import multivariate_normal
>>> x = np.linspace(0, 5, 10, endpoint=False)
>>> y = multivariate_normal.pdf(x, mean=2.5, cov=0.5); y
@ -294,16 +343,17 @@ class multivariate_normal_gen(object):
def __init__(self):
self.__doc__ = doccer.docformat(self.__doc__, docdict_params)
def __call__(self, mean=None, cov=1):
def __call__(self, mean=None, cov=1, allow_singular=False):
"""
Create a frozen multivariate normal distribution.
See `multivariate_normal_frozen` for more information.
"""
return multivariate_normal_frozen(mean, cov)
return multivariate_normal_frozen(mean, cov,
allow_singular=allow_singular)
def _logpdf(self, x, mean, prec_U, log_det_cov):
def _logpdf(self, x, mean, prec_U, log_det_cov, rank):
"""
Parameters
----------
@ -317,6 +367,8 @@ class multivariate_normal_gen(object):
is the precision matrix, i.e. inverse of the covariance matrix.
log_det_cov : float
Logarithm of the determinant of the covariance matrix
rank : int
Rank of the covariance matrix.
Notes
-----
@ -324,12 +376,11 @@ class multivariate_normal_gen(object):
called directly; use 'logpdf' instead.
"""
dim = x.shape[-1]
dev = x - mean
maha = np.sum(np.square(np.dot(dev, prec_U)), axis=-1)
return -0.5 * (dim * _LOG_2PI + log_det_cov + maha)
return -0.5 * (rank * _LOG_2PI + log_det_cov + maha)
def logpdf(self, x, mean, cov):
def logpdf(self, x, mean, cov, allow_singular=False):
"""
Log of the multivariate normal probability density function.
@ -351,11 +402,11 @@ class multivariate_normal_gen(object):
"""
dim, mean, cov = _process_parameters(None, mean, cov)
x = _process_quantiles(x, dim)
prec_U, log_det_cov = _psd_pinv_decomposed_log_pdet(cov)
out = self._logpdf(x, mean, prec_U, log_det_cov)
psd = _PSD(cov, allow_singular=allow_singular)
out = self._logpdf(x, mean, psd.U, psd.log_pdet, psd.rank)
return _squeeze_output(out)
def pdf(self, x, mean, cov):
def pdf(self, x, mean, cov, allow_singular=False):
"""
Multivariate normal probability density function.
@ -377,8 +428,8 @@ class multivariate_normal_gen(object):
"""
dim, mean, cov = _process_parameters(None, mean, cov)
x = _process_quantiles(x, dim)
prec_U, log_det_cov = _psd_pinv_decomposed_log_pdet(cov)
out = np.exp(self._logpdf(x, mean, prec_U, log_det_cov))
psd = _PSD(cov, allow_singular=allow_singular)
out = np.exp(self._logpdf(x, mean, psd.U, psd.log_pdet, psd.rank))
return _squeeze_output(out)
def rvs(self, mean=None, cov=1, size=1):
@ -425,13 +476,14 @@ class multivariate_normal_gen(object):
"""
dim, mean, cov = _process_parameters(None, mean, cov)
return 1/2 * np.log(np.linalg.det(2 * np.pi * np.e * cov))
return 0.5 * np.log(np.linalg.det(2 * np.pi * np.e * cov))
multivariate_normal = multivariate_normal_gen()
class multivariate_normal_frozen(object):
def __init__(self, mean=None, cov=1):
def __init__(self, mean=None, cov=1, allow_singular=False):
"""
Create a frozen multivariate normal distribution.
@ -441,6 +493,9 @@ class multivariate_normal_frozen(object):
Mean of the distribution (default zero)
cov : array_like, optional
Covariance matrix of the distribution (default one)
allow_singular : bool, optional
If this flag is True then tolerate a singular
covariance matrix (default False).
Examples
--------
@ -456,13 +511,13 @@ class multivariate_normal_frozen(object):
"""
self.dim, self.mean, self.cov = _process_parameters(None, mean, cov)
self.prec_U, self._log_det_cov = _psd_pinv_decomposed_log_pdet(self.cov)
self.cov_info = _PSD(self.cov, allow_singular=allow_singular)
self._mnorm = multivariate_normal_gen()
def logpdf(self, x):
x = _process_quantiles(x, self.dim)
out = self._mnorm._logpdf(x, self.mean, self.prec_U, self._log_det_cov)
out = self._mnorm._logpdf(x, self.mean, self.cov_info.U,
self.cov_info.log_pdet, self.cov_info.rank)
return _squeeze_output(out)
def pdf(self, x):
@ -481,7 +536,9 @@ class multivariate_normal_frozen(object):
Entropy of the multivariate normal distribution
"""
return 1/2 * (self.dim * (_LOG_2PI + 1) + self._log_det_cov)
log_pdet = self.cov_info.log_pdet
rank = self.cov_info.rank
return 0.5 * (rank * (_LOG_2PI + 1) + log_pdet)
# Set frozen generator docstrings from corresponding docstrings in
@ -491,3 +548,337 @@ for name in ['logpdf', 'pdf', 'rvs']:
method_frozen = multivariate_normal_frozen.__dict__[name]
method_frozen.__doc__ = doccer.docformat(method.__doc__, docdict_noparams)
method.__doc__ = doccer.docformat(method.__doc__, docdict_params)
_dirichlet_doc_default_callparams = """\
alpha : array_like
The concentration parameters. The number of entries determines the
dimensionality of the distribution.
"""
_dirichlet_doc_frozen_callparams = ""
_dirichlet_doc_frozen_callparams_note = \
"""See class definition for a detailed description of parameters."""
dirichlet_docdict_params = {
'_dirichlet_doc_default_callparams': _dirichlet_doc_default_callparams,
}
dirichlet_docdict_noparams = {
'_dirichlet_doc_default_callparams': _dirichlet_doc_frozen_callparams,
}
def _dirichlet_check_parameters(alpha):
alpha = np.asarray(alpha)
if np.min(alpha) <= 0:
raise ValueError("All parameters must be greater than 0")
elif alpha.ndim != 1:
raise ValueError("Parameter vector 'a' must be one dimensional, " +
"but a.shape = %s." % str(alpha.shape))
return alpha
def _dirichlet_check_input(alpha, x):
x = np.asarray(x)
if x.shape[0] + 1 != alpha.shape[0] and x.shape[0] != alpha.shape[0]:
raise ValueError("Vector 'x' must have one entry less then the" +
" parameter vector 'a', but alpha.shape = " +
"%s and " % alpha.shape +
"x.shape = %s." % x.shape)
if x.shape[0] != alpha.shape[0]:
xk = np.array([1 - np.sum(x, 0)])
if xk.ndim == 1:
x = np.append(x, xk)
elif xk.ndim == 2:
x = np.vstack((x, xk))
else:
raise ValueError("The input must be one dimensional or a two "
"dimensional matrix containing the entries.")
if np.min(x) < 0:
raise ValueError("Each entry in 'x' must be greater or equal zero.")
if np.max(x) > 1:
raise ValueError("Each entry in 'x' must be smaller or equal one.")
if (np.abs(np.sum(x, 0) - 1.0) > 10e-10).any():
raise ValueError("The input vector 'x' must lie within the normal " +
"simplex. but sum(x)=%f." % np.sum(x, 0))
return x
def _lnB(alpha):
r"""
Internal helper function to compute the log of the useful quotient
.. math::
B(\alpha) = \frac{\prod_{i=1}{K}\Gamma(\alpha_i)}{\Gamma\left(\sum_{i=1}^{K}\alpha_i\right)}
Parameters
----------
%(_dirichlet_doc_default_callparams)s
Returns
-------
B : scalar
Helper quotient, internal use only
"""
return np.sum(gammaln(alpha)) - gammaln(np.sum(alpha))
class dirichlet_gen(object):
r"""
A Dirichlet random variable.
The `alpha` keyword specifies the concentration parameters of the
distribution.
.. versionadded:: 0.15.0
Methods
-------
pdf(x, alpha)
Probability density function.
logpdf(x, alpha)
Log of the probability density function.
rvs(alpha, size=1)
Draw random samples from a Dirichlet distribution.
mean(alpha)
The mean of the Dirichlet distribution
var(alpha)
The variance of the Dirichlet distribution
entropy(alpha)
Compute the differential entropy of the multivariate normal.
Parameters
----------
x : array_like
Quantiles, with the last axis of `x` denoting the components.
%(_dirichlet_doc_default_callparams)s
Alternatively, the object may be called (as a function) to fix
concentration parameters, returning a "frozen" Dirichlet
random variable:
rv = dirichlet(alpha)
- Frozen object with the same methods but holding the given
concentration parameters fixed.
Notes
-----
Each :math:`\alpha` entry must be positive. The distribution has only
support on the simplex defined by
.. math::
\sum_{i=1}^{K} x_i \le 1
The probability density function for `dirichlet` is
.. math::
f(x) = \frac{1}{\mathrm{B}(\boldsymbol\alpha)} \prod_{i=1}^K x_i^{\alpha_i - 1}
where
.. math::
\mathrm{B}(\boldsymbol\alpha) = \frac{\prod_{i=1}^K \Gamma(\alpha_i)}{\Gamma\bigl(\sum_{i=1}^K \alpha_i\bigr)}
and :math:`\boldsymbol\alpha=(\alpha_1,\ldots,\alpha_K)`, the
concentration parameters and :math:`K` is the dimension of the space
where :math:`x` takes values.
"""
def __init__(self):
self.__doc__ = doccer.docformat(self.__doc__, dirichlet_docdict_params)
def __call__(self, alpha):
return dirichlet_frozen(alpha)
def _logpdf(self, x, alpha):
"""
Parameters
----------
x : ndarray
Points at which to evaluate the log of the probability
density function
%(_dirichlet_doc_default_callparams)s
Notes
-----
As this function does no argument checking, it should not be
called directly; use 'logpdf' instead.
"""
lnB = _lnB(alpha)
return - lnB + np.sum((np.log(x.T) * (alpha - 1)).T, 0)
def logpdf(self, x, alpha):
"""
Log of the Dirichlet probability density function.
Parameters
----------
x : array_like
Quantiles, with the last axis of `x` denoting the components.
%(_dirichlet_doc_default_callparams)s
Returns
-------
pdf : ndarray
Log of the probability density function evaluated at `x`
"""
alpha = _dirichlet_check_parameters(alpha)
x = _dirichlet_check_input(alpha, x)
out = self._logpdf(x, alpha)
return _squeeze_output(out)
def pdf(self, x, alpha):
"""
The Dirichlet probability density function.
Parameters
----------
x : array_like
Quantiles, with the last axis of `x` denoting the components.
%(_dirichlet_doc_default_callparams)s
Returns
-------
pdf : ndarray
The probability density function evaluated at `x`
"""
alpha = _dirichlet_check_parameters(alpha)
x = _dirichlet_check_input(alpha, x)
out = np.exp(self._logpdf(x, alpha))
return _squeeze_output(out)
def mean(self, alpha):
"""
Compute the mean of the dirichlet distribution.
Parameters
----------
%(_dirichlet_doc_default_callparams)s
Returns
-------
mu : scalar
Mean of the Dirichlet distribution
"""
alpha = _dirichlet_check_parameters(alpha)
out = alpha / (np.sum(alpha))
return _squeeze_output(out)
def var(self, alpha):
"""
Compute the variance of the dirichlet distribution.
Parameters
----------
%(_dirichlet_doc_default_callparams)s
Returns
-------
v : scalar
Variance of the Dirichlet distribution
"""
alpha = _dirichlet_check_parameters(alpha)
alpha0 = np.sum(alpha)
out = (alpha * (alpha0 - alpha)) / ((alpha0 * alpha0) * (alpha0 + 1))
return out
def entropy(self, alpha):
"""
Compute the differential entropy of the dirichlet distribution.
Parameters
----------
%(_dirichlet_doc_default_callparams)s
Returns
-------
h : scalar
Entropy of the Dirichlet distribution
"""
alpha = _dirichlet_check_parameters(alpha)
alpha0 = np.sum(alpha)
lnB = _lnB(alpha)
K = alpha.shape[0]
out = lnB + (alpha0 - K) * scipy.special.psi(alpha0) - np.sum(
(alpha - 1) * scipy.special.psi(alpha))
return _squeeze_output(out)
def rvs(self, alpha, size=1):
"""
Draw random samples from a Dirichlet distribution.
Parameters
----------
%(_dirichlet_doc_default_callparams)s
size : integer, optional
Number of samples to draw (default 1).
Returns
-------
rvs : ndarray or scalar
Random variates of size (`size`, `N`), where `N` is the
dimension of the random variable.
"""
alpha = _dirichlet_check_parameters(alpha)
return np.random.dirichlet(alpha, size=size)
dirichlet = dirichlet_gen()
class dirichlet_frozen(object):
def __init__(self, alpha):
self.alpha = _dirichlet_check_parameters(alpha)
self._dirichlet = dirichlet_gen()
def logpdf(self, x):
return self._dirichlet.logpdf(x, self.alpha)
def pdf(self, x):
return self._dirichlet.pdf(x, self.alpha)
def mean(self):
return self._dirichlet.mean(self.alpha)
def var(self):
return self._dirichlet.var(self.alpha)
def entropy(self):
return self._dirichlet.entropy(self.alpha)
def rvs(self, size=1):
return self._dirichlet.rvs(self.alpha, size)
# Set frozen generator docstrings from corresponding docstrings in
# multivariate_normal_gen and fill in default strings in class docstrings
for name in ['logpdf', 'pdf', 'rvs', 'mean', 'var', 'entropy']:
method = dirichlet_gen.__dict__[name]
method_frozen = dirichlet_frozen.__dict__[name]
method_frozen.__doc__ = doccer.docformat(
method.__doc__, dirichlet_docdict_noparams)
method.__doc__ = doccer.docformat(method.__doc__, dirichlet_docdict_params)

@ -0,0 +1,54 @@
"""Functions copypasted from newer versions of numpy.
"""
from __future__ import division, print_function, absolute_import
import warnings
import numpy as np
from scipy.lib._version import NumpyVersion
if NumpyVersion(np.__version__) > '1.7.0.dev':
_assert_warns = np.testing.assert_warns
else:
def _assert_warns(warning_class, func, *args, **kw):
r"""
Fail unless the given callable throws the specified warning.
This definition is copypasted from numpy 1.9.0.dev.
The version in earlier numpy returns None.
Parameters
----------
warning_class : class
The class defining the warning that `func` is expected to throw.
func : callable
The callable to test.
*args : Arguments
Arguments passed to `func`.
**kwargs : Kwargs
Keyword arguments passed to `func`.
Returns
-------
The value returned by `func`.
"""
with warnings.catch_warnings(record=True) as l:
warnings.simplefilter('always')
result = func(*args, **kw)
if not len(l) > 0:
raise AssertionError("No warning raised when calling %s"
% func.__name__)
if not l[0].category is warning_class:
raise AssertionError("First warning for %s is not a "
"%s( is %s)" % (func.__name__, warning_class, l[0]))
return result
if NumpyVersion(np.__version__) >= '1.6.0':
count_nonzero = np.count_nonzero
else:
def count_nonzero(a):
return (a != 0).sum()

@ -246,9 +246,9 @@ def chi2_contingency(observed, correction=True, lambda_=None):
if np.any(expected == 0):
# Include one of the positions where expected is zero in
# the exception message.
zeropos = list(np.where(expected == 0)[0])
zeropos = list(zip(*np.where(expected == 0)))[0]
raise ValueError("The internally computed table of expected "
"frequencies has a zero element at %s." % zeropos)
"frequencies has a zero element at %s." % (zeropos,))
# The degrees of freedom
dof = expected.size - sum(expected.shape) + expected.ndim - 1

@ -1,6 +1,6 @@
from __future__ import division
import warnings
from wafo.wafodata import PlotData
from wafo.containers import PlotData
from wafo.misc import findextrema
from scipy import special
import numpy as np

@ -7,7 +7,19 @@
#
from __future__ import division, print_function, absolute_import
from ._distn_infrastructure import entropy, rv_discrete, rv_continuous
from ._distn_infrastructure import (entropy, rv_discrete, rv_continuous,
rv_frozen)
from . import _continuous_distns
from . import _discrete_distns
from ._continuous_distns import *
from ._discrete_distns import *
# For backwards compatibility e.g. pymc expects distributions.__all__.
__all__ = ['entropy', 'rv_discrete', 'rv_continuous']
# Add only the distribution names, not the *_gen names.
__all__ += _continuous_distns._distn_names
__all__ += _discrete_distns._distn_names

@ -7,10 +7,11 @@ Distributions
Author: Per A. Brodtkorb 2008
'''
from __future__ import division
from __future__ import division, absolute_import
import warnings
from wafo.plotbackend import plotbackend
from wafo.misc import ecross, findcross
from ..plotbackend import plotbackend
from ..misc import ecross, findcross
import numdifftools # @UnresolvedImport
@ -27,12 +28,10 @@ from numpy import (
from numpy import flatnonzero as nonzero
__all__ = [
'Profile', 'FitDistribution'
]
__all__ = ['Profile', 'FitDistribution']
floatinfo = np.finfo(float)
# arr = atleast_1d
arr = asarray
all = alltrue # @ReservedAssignment
@ -77,7 +76,8 @@ class rv_frozen(object):
def __init__(self, dist, *args, **kwds):
self.dist = dist
args, loc, scale = dist._parse_args(*args, **kwds)
if len(args) == dist.numargs - 2: # isinstance(dist, rv_continuous):
if len(args) == dist.numargs - 2: #
# if isinstance(dist, rv_continuous):
self.par = args + (loc, scale)
else: # rv_discrete
self.par = args + (loc,)
@ -283,27 +283,25 @@ class Profile(object):
self._par = phatv.copy()
# Set up variable to profile and _local_link function
self.profile_x = not self.x == None
self.profile_logSF = not (self.logSF == None or self.profile_x)
self.profile_x = self.x is not None
self.profile_logSF = not (self.logSF is None or self.profile_x)
self.profile_par = not (self.profile_x or self.profile_logSF)
if self.link == None:
if self.link is None:
self.link = self.fit_dist.dist.link
if self.profile_par:
self._local_link = lambda fix_par, par: fix_par
self._local_link = self._par_link
self.xlabel = 'phat(%d)' % self.i_fixed
p_opt = self._par[self.i_fixed]
elif self.profile_x:
self.logSF = fit_dist.logsf(self.x)
self._local_link = lambda fix_par, par: self.link(
fix_par, self.logSF, par, self.i_fixed)
self._local_link = self._x_link
self.xlabel = 'x'
p_opt = self.x
elif self.profile_logSF:
p_opt = self.logSF
self.x = fit_dist.isf(exp(p_opt))
self._local_link = lambda fix_par, par: self.link(
self.x, fix_par, par, self.i_fixed)
self._local_link = self._logSF_link
self.xlabel = 'log(SF)'
else:
raise ValueError(
@ -315,6 +313,15 @@ class Profile(object):
phatfree = phatv[self.i_free].copy()
self._set_profile(phatfree, p_opt)
def _par_link(self, fix_par, par):
return fix_par
def _x_link(self, fix_par, par):
return self.link(fix_par, self.logSF, par, self.i_fixed)
def _logSF_link(self, fix_par, par):
return self.link(self.x, fix_par, par, self.i_fixed)
def _correct_Lmax(self, Lmax):
if Lmax > self.Lmax: # foundNewphat = True
warnings.warn(
@ -386,7 +393,7 @@ class Profile(object):
'''
linspace = numpy.linspace
if self.pmin == None or self.pmax == None:
if self.pmin is None or self.pmax is None:
pvar = self._get_variance()
@ -395,12 +402,12 @@ class Profile(object):
p_crit = (-norm_ppf(self.alpha / 2.0) *
sqrt(numpy.ravel(pvar)) * 1.5)
if self.pmin == None:
if self.pmin is None:
self.pmin = self._search_pmin(phatfree0,
p_opt - 5.0 * p_crit, p_opt)
p_crit_low = (p_opt - self.pmin) / 5
if self.pmax == None:
if self.pmax is None:
self.pmax = self._search_pmax(phatfree0,
p_opt + 5.0 * p_crit, p_opt)
p_crit_up = (self.pmax - p_opt) / 5
@ -533,59 +540,13 @@ class Profile(object):
self.args[[0, -1]], [self.Lmax, ] * 2, 'r--',
self.args[[0, -1]], [self.alpha_cross_level, ] * 2, 'r--')
axis.vlines(p_ci, ymin=axis.get_ylim()[0],
ymax=self.Lmax, #self.alpha_cross_level,
ymax=self.Lmax, # self.alpha_cross_level,
color='r', linestyles='--')
axis.set_title(self.title)
axis.set_ylabel(self.ylabel)
axis.set_xlabel(self.xlabel)
def _discretize_adaptive(fun, a, b, tol=0.005, n=5):
'''
Automatic discretization of function, adaptive gridding.
'''
tiny = floatinfo.tiny
n += (np.mod(n, 2) == 0) # make sure n is odd
x = np.linspace(a, b, n)
fx = fun(x)
n2 = (n - 1) / 2
erri = np.hstack((np.zeros((n2, 1)), np.ones((n2, 1)))).ravel()
err = erri.max()
err0 = np.inf
# while (err != err0 and err > tol and n < nmax):
for j in range(50):
if err != err0 and np.any(erri > tol):
err0 = err
# find top errors
I, = np.where(erri > tol)
# double the sample rate in intervals with the most error
y = (np.vstack(((x[I] + x[I - 1]) / 2,
(x[I + 1] + x[I]) / 2)).T).ravel()
fy = fun(y)
fy0 = np.interp(y, x, fx)
erri = 0.5 * (abs((fy0 - fy) / (abs(fy0 + fy) + tiny)))
err = erri.max()
x = np.hstack((x, y))
I = x.argsort()
x = x[I]
erri = np.hstack((zeros(len(fx)), erri))[I]
fx = np.hstack((fx, fy))[I]
else:
break
else:
warnings.warn('Recursion level limit reached j=%d' % j)
return x, fx
# class to fit given distribution to data
class FitDistribution(rv_frozen):
'''
@ -867,7 +828,7 @@ class FitDistribution(rv_frozen):
def _compute_cov(self):
'''Compute covariance
'''
somefixed = (self.par_fix != None) and any(isfinite(self.par_fix))
somefixed = (self.par_fix is not None) and any(isfinite(self.par_fix))
# H1 = numpy.asmatrix(self.dist.hessian_nnlf(self.par, self.data))
H = numpy.asmatrix(self.dist.hessian_nlogps(self.par, self.data))
self.H = H
@ -1000,7 +961,7 @@ class FitDistribution(rv_frozen):
self.plotresprb()
fixstr = ''
if not self.par_fix == None:
if self.par_fix is not None:
numfix = len(self.i_fixed)
if numfix > 0:
format0 = ', '.join(['%d'] * numfix)
@ -1160,7 +1121,7 @@ class FitDistribution(rv_frozen):
n = len(x)
np1 = n + 1
if unknown_numpar == None:
if unknown_numpar is None:
k = len(theta)
else:
k = unknown_numpar
@ -1184,7 +1145,7 @@ def test_doctstrings():
def test1():
import wafo.stats as ws
dist = ws.weibull_min
#dist = ws.bradford
# dist = ws.bradford
R = dist.rvs(0.3, size=1000)
phat = FitDistribution(dist, R, method='ml')

@ -93,6 +93,10 @@ class gaussian_kde(object):
high_bounds.
kde.integrate_kde(other_kde) : float
Integrate two kernel density estimates multiplied together.
kde.pdf(points) : ndarray
Alias for ``kde.evaluate(points)``.
kde.logpdf(points) : ndarray
Equivalent to ``np.log(kde.evaluate(points))``.
kde.resample(size=None) : ndarray
Randomly sample a dataset from the estimated pdf.
kde.set_bandwidth(bw_method='scott') : None
@ -106,7 +110,6 @@ class gaussian_kde(object):
to provide a different method, or set it through a call to
`kde.set_bandwidth`.
Notes
-----
Bandwidth selection strongly influences the estimate obtained from the KDE
@ -122,7 +125,7 @@ class gaussian_kde(object):
with ``n`` the number of data points and ``d`` the number of dimensions.
Silverman's Rule [2]_, implemented as `silverman_factor`, is::
n * (d + 2) / 4.)**(-1. / (d + 4)).
(n * (d + 2) / 4.)**(-1. / (d + 4)).
Good general descriptions of kernel density estimation can be found in [1]_
and [2]_, the mathematics for this multi-dimensional implementation can be
@ -388,11 +391,12 @@ class gaussian_kde(object):
large = other
sum_cov = small.covariance + large.covariance
sum_cov_chol = linalg.cho_factor(sum_cov)
result = 0.0
for i in range(small.n):
mean = small.dataset[:, i, newaxis]
diff = large.dataset - mean
tdiff = dot(linalg.inv(sum_cov), diff)
tdiff = linalg.cho_solve(sum_cov_chol, diff)
energies = sum(diff * tdiff, axis=0) / 2.0
result += sum(exp(-energies), axis=0)
@ -511,3 +515,27 @@ class gaussian_kde(object):
self.covariance = self._data_covariance * self.factor**2
self.inv_cov = self._data_inv_cov / self.factor**2
self._norm_factor = sqrt(linalg.det(2*pi*self.covariance)) * self.n
def pdf(self, x):
"""
Evaluate the estimated pdf on a provided set of points.
Notes
-----
This is an alias for `gaussian_kde.evaluate`. See the ``evaluate``
docstring for more details.
"""
return self.evaluate(x)
def logpdf(self, x):
"""
Evaluate the log of the estimated pdf on a provided set of points.
Notes
-----
See `gaussian_kde.evaluate` for more details; this method simply
returns ``np.log(gaussian_kde.evaluate(x))``.
"""
return np.log(self.evaluate(x))

File diff suppressed because it is too large Load Diff

@ -24,13 +24,9 @@ is a relatively new package, some API changes are still possible.
f_value_wilks_lambda
find_repeats
friedmanchisquare
gmean
hmean
kendalltau
kendalltau_seasonal
kruskalwallis
kruskalwallis
ks_twosamp
ks_twosamp
kurtosis
kurtosistest
@ -80,3 +76,4 @@ from __future__ import division, print_function, absolute_import
from .mstats_basic import *
from .mstats_extras import *
from scipy.stats import gmean, hmean

File diff suppressed because it is too large Load Diff

@ -1,15 +1,12 @@
"""
Additional statistics functions, with support to MA.
Additional statistics functions with support for masked arrays.
:author: Pierre GF Gerard-Marchant
:contact: pierregm_at_uga_edu
:date: $Date: 2007-10-29 17:18:13 +0200 (Mon, 29 Oct 2007) $
:version: $Id: morestats.py 3473 2007-10-29 15:18:13Z jarrod.millman $
"""
from __future__ import division, print_function, absolute_import
__author__ = "Pierre GF Gerard-Marchant"
__docformat__ = "restructuredtext en"
# Original author (2007): Pierre GF Gerard-Marchant
from __future__ import division, print_function, absolute_import
__all__ = ['compare_medians_ms',
@ -19,6 +16,7 @@ __all__ = ['compare_medians_ms',
'rsh',
'trimmed_mean_ci',]
import numpy as np
from numpy import float_, int_, ndarray
@ -30,9 +28,6 @@ from . import mstats_basic as mstats
from scipy.stats.distributions import norm, beta, t, binom
#####--------------------------------------------------------------------------
#---- --- Quantiles ---
#####--------------------------------------------------------------------------
def hdquantiles(data, prob=list([.25,.5,.75]), axis=None, var=False,):
"""
Computes quantile estimates with the Harrell-Davis method.
@ -65,14 +60,14 @@ def hdquantiles(data, prob=list([.25,.5,.75]), axis=None, var=False,):
xsorted = np.squeeze(np.sort(data.compressed().view(ndarray)))
# Don't use length here, in case we have a numpy scalar
n = xsorted.size
#.........
hd = np.empty((2,len(prob)), float_)
if n < 2:
hd.flat = np.nan
if var:
return hd
return hd[0]
#.........
v = np.arange(n+1) / float(n)
betacdf = beta.cdf
for (i,p) in enumerate(prob):
@ -89,7 +84,7 @@ def hdquantiles(data, prob=list([.25,.5,.75]), axis=None, var=False,):
hd[1, prob == 0] = hd[1, prob == 1] = np.nan
return hd
return hd[0]
# Initialization & checks ---------
# Initialization & checks
data = ma.array(data, copy=False, dtype=float_)
p = np.array(prob, copy=False, ndmin=1)
# Computes quantiles along axis (or globally)
@ -97,12 +92,11 @@ def hdquantiles(data, prob=list([.25,.5,.75]), axis=None, var=False,):
result = _hd_1D(data, p, var)
else:
if data.ndim > 2:
raise ValueError("Array 'data' must be at most two dimensional, but got data.ndim = %d" % data.ndim)
raise ValueError("Array 'data' must be at most two dimensional, "
"but got data.ndim = %d" % data.ndim)
result = ma.apply_along_axis(_hd_1D, axis, data, p, var)
#
return ma.fix_invalid(result, copy=False)
#..............................................................................
return ma.fix_invalid(result, copy=False)
def hdmedian(data, axis=-1, var=False):
@ -124,7 +118,6 @@ def hdmedian(data, axis=-1, var=False):
return result.squeeze()
#..............................................................................
def hdquantiles_sd(data, prob=list([.25,.5,.75]), axis=None):
"""
The standard error of the Harrell-Davis quantile estimates by jackknife.
@ -153,10 +146,10 @@ def hdquantiles_sd(data, prob=list([.25,.5,.75]), axis=None):
hdsd = np.empty(len(prob), float_)
if n < 2:
hdsd.flat = np.nan
#.........
vv = np.arange(n) / float(n-1)
betacdf = beta.cdf
#
for (i,p) in enumerate(prob):
_w = betacdf(vv, (n+1)*p, (n+1)*(1-p))
w = _w[1:] - _w[:-1]
@ -166,7 +159,7 @@ def hdquantiles_sd(data, prob=list([.25,.5,.75]), axis=None):
mx_var = np.array(mx_.var(), copy=False, ndmin=1) * n / float(n-1)
hdsd[i] = float(n-1) * np.sqrt(np.diag(mx_var).diagonal() / float(n))
return hdsd
# Initialization & checks ---------
# Initialization & checks
data = ma.array(data, copy=False, dtype=float_)
p = np.array(prob, copy=False, ndmin=1)
# Computes quantiles along axis (or globally)
@ -174,15 +167,12 @@ def hdquantiles_sd(data, prob=list([.25,.5,.75]), axis=None):
result = _hdsd_1D(data, p)
else:
if data.ndim > 2:
raise ValueError("Array 'data' must be at most two dimensional, but got data.ndim = %d" % data.ndim)
raise ValueError("Array 'data' must be at most two dimensional, "
"but got data.ndim = %d" % data.ndim)
result = ma.apply_along_axis(_hdsd_1D, axis, data, p)
#
return ma.fix_invalid(result, copy=False).ravel()
return ma.fix_invalid(result, copy=False).ravel()
#####--------------------------------------------------------------------------
#---- --- Confidence intervals ---
#####--------------------------------------------------------------------------
def trimmed_mean_ci(data, limits=(0.2,0.2), inclusive=(True,True),
alpha=0.05, axis=None):
@ -198,9 +188,9 @@ def trimmed_mean_ci(data, limits=(0.2,0.2), inclusive=(True,True),
Tuple of the percentages to cut on each side of the array, with respect
to the number of unmasked data, as floats between 0. and 1. If ``n``
is the number of unmasked data before trimming, then
(``n`` * `limits[0]`)th smallest data and (``n`` * `limits[1]`)th
(``n * limits[0]``)th smallest data and (``n * limits[1]``)th
largest data are masked. The total number of unmasked data after
trimming is ``n`` * (1. - sum(`limits`)).
trimming is ``n * (1. - sum(limits))``.
The value of one limit can be set to None to indicate an open interval.
Defaults to (0.2, 0.2).
@ -234,8 +224,6 @@ def trimmed_mean_ci(data, limits=(0.2,0.2), inclusive=(True,True),
tppf = t.ppf(1-alpha/2.,df)
return np.array((tmean - tppf*tstde, tmean+tppf*tstde))
#..............................................................................
def mjci(data, prob=[0.25,0.5,0.75], axis=None):
"""
@ -258,7 +246,7 @@ def mjci(data, prob=[0.25,0.5,0.75], axis=None):
n = data.size
prob = (np.array(p) * n + 0.5).astype(int_)
betacdf = beta.cdf
#
mj = np.empty(len(prob), float_)
x = np.arange(1,n+1, dtype=float_) / n
y = x - 1./n
@ -269,10 +257,12 @@ def mjci(data, prob=[0.25,0.5,0.75], axis=None):
C2 = np.dot(W,data**2)
mj[i] = np.sqrt(C2 - C1**2)
return mj
#
data = ma.array(data, copy=False)
if data.ndim > 2:
raise ValueError("Array 'data' must be at most two dimensional, but got data.ndim = %d" % data.ndim)
raise ValueError("Array 'data' must be at most two dimensional, "
"but got data.ndim = %d" % data.ndim)
p = np.array(prob, copy=False, ndmin=1)
# Computes quantiles along axis (or globally)
if (axis is None):
@ -280,8 +270,6 @@ def mjci(data, prob=[0.25,0.5,0.75], axis=None):
else:
return ma.apply_along_axis(_mjci_1D, axis, data, p)
#..............................................................................
def mquantiles_cimj(data, prob=[0.25,0.50,0.75], alpha=0.05, axis=None):
"""
@ -308,7 +296,6 @@ def mquantiles_cimj(data, prob=[0.25,0.50,0.75], alpha=0.05, axis=None):
return (xq - z * smj, xq + z * smj)
#.............................................................................
def median_cihs(data, alpha=0.05, axis=None):
"""
Computes the alpha-level confidence interval for the median of the data.
@ -353,12 +340,11 @@ def median_cihs(data, alpha=0.05, axis=None):
result = _cihs_1D(data.compressed(), alpha)
else:
if data.ndim > 2:
raise ValueError("Array 'data' must be at most two dimensional, but got data.ndim = %d" % data.ndim)
raise ValueError("Array 'data' must be at most two dimensional, "
"but got data.ndim = %d" % data.ndim)
result = ma.apply_along_axis(_cihs_1D, axis, data, alpha)
#
return result
#..............................................................................
return result
def compare_medians_ms(group_1, group_2, axis=None):
@ -453,14 +439,13 @@ def rsh(data, points=None):
points = data
else:
points = np.array(points, copy=False, ndmin=1)
if data.ndim != 1:
raise AttributeError("The input array should be 1D only !")
n = data.count()
r = idealfourths(data, axis=None)
h = 1.2 * (r[-1]-r[0]) / n**(1./5)
nhi = (data[:,None] <= points[None,:] + h).sum(0)
nlo = (data[:,None] < points[None,:] - h).sum(0)
return (nhi-nlo) / (2.*n*h)
###############################################################################

File diff suppressed because it is too large Load Diff

@ -6,12 +6,11 @@ import warnings
import numpy as np
import numpy.testing as npt
#from scipy.lib._version import NumpyVersion
from scipy import stats
from scipy.lib._version import NumpyVersion
from wafo import stats
#NUMPY_BELOW_1_7 = NumpyVersion(np.__version__) < '1.7.0'
NUMPY_BELOW_1_7 = np.__version__ < '1.7.0'
NUMPY_BELOW_1_7 = NumpyVersion(np.__version__) < '1.7.0'
def check_normalization(distfn, args, distname):
@ -60,14 +59,14 @@ def check_mean_expect(distfn, arg, m, msg):
def check_var_expect(distfn, arg, m, v, msg):
if np.isfinite(v):
m2 = distfn.expect(lambda x: x * x, arg)
npt.assert_almost_equal(m2, v + m * m, decimal=5, err_msg=msg +
m2 = distfn.expect(lambda x: x*x, arg)
npt.assert_almost_equal(m2, v + m*m, decimal=5, err_msg=msg +
' - 2st moment (expect)')
def check_skew_expect(distfn, arg, m, v, s, msg):
if np.isfinite(s):
m3e = distfn.expect(lambda x: np.power(x - m, 3), arg)
m3e = distfn.expect(lambda x: np.power(x-m, 3), arg)
npt.assert_almost_equal(m3e, s * np.power(v, 1.5),
decimal=5, err_msg=msg + ' - skew')
else:
@ -76,9 +75,8 @@ def check_skew_expect(distfn, arg, m, v, s, msg):
def check_kurt_expect(distfn, arg, m, v, k, msg):
if np.isfinite(k):
m4e = distfn.expect(lambda x: np.power(x - m, 4), arg)
npt.assert_allclose(
m4e, (k + 3.) * np.power(v, 2), atol=1e-5, rtol=1e-5,
m4e = distfn.expect(lambda x: np.power(x-m, 4), arg)
npt.assert_allclose(m4e, (k + 3.) * np.power(v, 2), atol=1e-5, rtol=1e-5,
err_msg=msg + ' - kurtosis')
else:
npt.assert_(np.isnan(k))
@ -106,7 +104,7 @@ def check_edge_support(distfn, args):
npt.assert_equal(distfn.logsf(x, *args), [0.0, -np.inf])
if isinstance(distfn, stats.rv_discrete):
x = [distfn.a - 1, distfn.b]
x = [distfn.a-1, distfn.b]
npt.assert_equal(distfn.ppf([0.0, 1.0], *args), x)
npt.assert_equal(distfn.isf([0.0, 1.0], *args), x[::-1])
@ -116,7 +114,7 @@ def check_edge_support(distfn, args):
def check_named_args(distfn, x, shape_args, defaults, meths):
# Check calling w/ named arguments.
## Check calling w/ named arguments.
# check consistency of shapes, numargs and _parse signature
signature = inspect.getargspec(distfn._parse_args)
@ -124,8 +122,7 @@ def check_named_args(distfn, x, shape_args, defaults, meths):
npt.assert_(signature.keywords is None)
npt.assert_(signature.defaults == defaults)
# self, a, b, loc=0, scale=1
shape_argnames = signature.args[1:-len(defaults)]
shape_argnames = signature.args[1:-len(defaults)] # self, a, b, loc=0, scale=1
if distfn.shapes:
shapes_ = distfn.shapes.replace(',', ' ').split()
else:
@ -144,7 +141,7 @@ def check_named_args(distfn, x, shape_args, defaults, meths):
k.update({names.pop(): a.pop()})
v = [meth(x, *a, **k) for meth in meths]
npt.assert_array_equal(vals, v)
if not 'n' in k.keys():
if 'n' not in k.keys():
# `n` is first parameter of moment(), so can't be used as named arg
with warnings.catch_warnings():
warnings.simplefilter("ignore", UserWarning)
@ -154,3 +151,4 @@ def check_named_args(distfn, x, shape_args, defaults, meths):
# unknown arguments should not go through:
k.update({'kaboom': 42})
npt.assert_raises(TypeError, distfn.cdf, x, **k)

@ -1,4 +1,5 @@
from __future__ import division, print_function, absolute_import
import numpy as np
from numpy.testing import assert_array_almost_equal, run_module_suite
from scipy.stats import \
@ -19,7 +20,7 @@ class TestBinnedStatistic(object):
x = self.x
v = self.v
count1, edges1, _bc = binned_statistic(x, v, 'count', bins=10)
count1, edges1, bc = binned_statistic(x, v, 'count', bins=10)
count2, edges2 = np.histogram(x, bins=10)
assert_array_almost_equal(count1, count2)
@ -29,7 +30,7 @@ class TestBinnedStatistic(object):
x = self.x
v = self.v
sum1, edges1, _bc = binned_statistic(x, v, 'sum', bins=10)
sum1, edges1, bc = binned_statistic(x, v, 'sum', bins=10)
sum2, edges2 = np.histogram(x, bins=10, weights=v)
assert_array_almost_equal(sum1, sum2)
@ -39,8 +40,8 @@ class TestBinnedStatistic(object):
x = self.x
v = self.v
stat1, edges1, _bc = binned_statistic(x, v, 'mean', bins=10)
stat2, edges2, _bc = binned_statistic(x, v, np.mean, bins=10)
stat1, edges1, bc = binned_statistic(x, v, 'mean', bins=10)
stat2, edges2, bc = binned_statistic(x, v, np.mean, bins=10)
assert_array_almost_equal(stat1, stat2)
assert_array_almost_equal(edges1, edges2)
@ -49,8 +50,8 @@ class TestBinnedStatistic(object):
x = self.x
v = self.v
stat1, edges1, _bc = binned_statistic(x, v, 'std', bins=10)
stat2, edges2, _bc = binned_statistic(x, v, np.std, bins=10)
stat1, edges1, bc = binned_statistic(x, v, 'std', bins=10)
stat2, edges2, bc = binned_statistic(x, v, np.std, bins=10)
assert_array_almost_equal(stat1, stat2)
assert_array_almost_equal(edges1, edges2)
@ -59,8 +60,8 @@ class TestBinnedStatistic(object):
x = self.x
v = self.v
stat1, edges1, _bc = binned_statistic(x, v, 'median', bins=10)
stat2, edges2, _bc = binned_statistic(x, v, np.median, bins=10)
stat1, edges1, bc = binned_statistic(x, v, 'median', bins=10)
stat2, edges2, bc = binned_statistic(x, v, np.median, bins=10)
assert_array_almost_equal(stat1, stat2)
assert_array_almost_equal(edges1, edges2)
@ -69,7 +70,7 @@ class TestBinnedStatistic(object):
x = self.x[:20]
v = self.v[:20]
count1, _edges1, bc = binned_statistic(x, v, 'count', bins=3)
count1, edges1, bc = binned_statistic(x, v, 'count', bins=3)
bc2 = np.array([3, 2, 1, 3, 2, 3, 3, 3, 3, 1, 1, 3, 3, 1, 2, 3, 1,
1, 2, 1])
@ -86,7 +87,7 @@ class TestBinnedStatistic(object):
mean, bins, _ = binned_statistic(x[:15], data[:15])
mean_range, bins_range, _ = binned_statistic(x, data, range=[(0, 14)])
mean_range2, bins_range2, _ = binned_statistic(x, data, range=[(0, 14)])
mean_range2, bins_range2, _ = binned_statistic(x, data, range=(0, 14))
assert_array_almost_equal(mean, mean_range)
assert_array_almost_equal(bins, bins_range)
@ -98,8 +99,7 @@ class TestBinnedStatistic(object):
y = self.y
v = self.v
count1, binx1, biny1, _bc = binned_statistic_2d(x, y, v, 'count',
bins=5)
count1, binx1, biny1, bc = binned_statistic_2d(x, y, v, 'count', bins=5)
count2, binx2, biny2 = np.histogram2d(x, y, bins=5)
assert_array_almost_equal(count1, count2)
@ -111,7 +111,7 @@ class TestBinnedStatistic(object):
y = self.y
v = self.v
sum1, binx1, biny1, _bc = binned_statistic_2d(x, y, v, 'sum', bins=5)
sum1, binx1, biny1, bc = binned_statistic_2d(x, y, v, 'sum', bins=5)
sum2, binx2, biny2 = np.histogram2d(x, y, bins=5, weights=v)
assert_array_almost_equal(sum1, sum2)
@ -123,8 +123,8 @@ class TestBinnedStatistic(object):
y = self.y
v = self.v
stat1, binx1, biny1, _b = binned_statistic_2d(x, y, v, 'mean', bins=5)
stat2, binx2, biny2, _b = binned_statistic_2d(x, y, v, np.mean, bins=5)
stat1, binx1, biny1, bc = binned_statistic_2d(x, y, v, 'mean', bins=5)
stat2, binx2, biny2, bc = binned_statistic_2d(x, y, v, np.mean, bins=5)
assert_array_almost_equal(stat1, stat2)
assert_array_almost_equal(binx1, binx2)
@ -135,8 +135,8 @@ class TestBinnedStatistic(object):
y = self.y
v = self.v
stat1, binx1, biny1, _bc = binned_statistic_2d(x, y, v, 'std', bins=5)
stat2, binx2, biny2, _bc = binned_statistic_2d(x, y, v, np.std, bins=5)
stat1, binx1, biny1, bc = binned_statistic_2d(x, y, v, 'std', bins=5)
stat2, binx2, biny2, bc = binned_statistic_2d(x, y, v, np.std, bins=5)
assert_array_almost_equal(stat1, stat2)
assert_array_almost_equal(binx1, binx2)
@ -147,9 +147,8 @@ class TestBinnedStatistic(object):
y = self.y
v = self.v
stat1, binx1, biny1, _ = binned_statistic_2d(x, y, v, 'median', bins=5)
stat2, binx2, biny2, _ = binned_statistic_2d(x, y, v, np.median,
bins=5)
stat1, binx1, biny1, bc = binned_statistic_2d(x, y, v, 'median', bins=5)
stat2, binx2, biny2, bc = binned_statistic_2d(x, y, v, np.median, bins=5)
assert_array_almost_equal(stat1, stat2)
assert_array_almost_equal(binx1, binx2)
@ -160,8 +159,7 @@ class TestBinnedStatistic(object):
y = self.y[:20]
v = self.v[:20]
count1, _binx1, _biny1, bc = binned_statistic_2d(x, y, v, 'count',
bins=3)
count1, binx1, biny1, bc = binned_statistic_2d(x, y, v, 'count', bins=3)
bc2 = np.array([17, 11, 6, 16, 11, 17, 18, 17, 17, 7, 6, 18, 16,
6, 11, 16, 6, 6, 11, 8])
@ -175,7 +173,7 @@ class TestBinnedStatistic(object):
X = self.X
v = self.v
count1, edges1, _bc = binned_statistic_dd(X, v, 'count', bins=3)
count1, edges1, bc = binned_statistic_dd(X, v, 'count', bins=3)
count2, edges2 = np.histogramdd(X, bins=3)
assert_array_almost_equal(count1, count2)
@ -185,7 +183,7 @@ class TestBinnedStatistic(object):
X = self.X
v = self.v
sum1, edges1, _bc = binned_statistic_dd(X, v, 'sum', bins=3)
sum1, edges1, bc = binned_statistic_dd(X, v, 'sum', bins=3)
sum2, edges2 = np.histogramdd(X, bins=3, weights=v)
assert_array_almost_equal(sum1, sum2)
@ -195,8 +193,8 @@ class TestBinnedStatistic(object):
X = self.X
v = self.v
stat1, edges1, _bc = binned_statistic_dd(X, v, 'mean', bins=3)
stat2, edges2, _bc = binned_statistic_dd(X, v, np.mean, bins=3)
stat1, edges1, bc = binned_statistic_dd(X, v, 'mean', bins=3)
stat2, edges2, bc = binned_statistic_dd(X, v, np.mean, bins=3)
assert_array_almost_equal(stat1, stat2)
assert_array_almost_equal(edges1, edges2)
@ -205,8 +203,8 @@ class TestBinnedStatistic(object):
X = self.X
v = self.v
stat1, edges1, _bc = binned_statistic_dd(X, v, 'std', bins=3)
stat2, edges2, _bc = binned_statistic_dd(X, v, np.std, bins=3)
stat1, edges1, bc = binned_statistic_dd(X, v, 'std', bins=3)
stat2, edges2, bc = binned_statistic_dd(X, v, np.std, bins=3)
assert_array_almost_equal(stat1, stat2)
assert_array_almost_equal(edges1, edges2)
@ -215,8 +213,8 @@ class TestBinnedStatistic(object):
X = self.X
v = self.v
stat1, edges1, _bc = binned_statistic_dd(X, v, 'median', bins=3)
stat2, edges2, _bc = binned_statistic_dd(X, v, np.median, bins=3)
stat1, edges1, bc = binned_statistic_dd(X, v, 'median', bins=3)
stat2, edges2, bc = binned_statistic_dd(X, v, np.median, bins=3)
assert_array_almost_equal(stat1, stat2)
assert_array_almost_equal(edges1, edges2)
@ -225,7 +223,7 @@ class TestBinnedStatistic(object):
X = self.X[:20]
v = self.v[:20]
count1, _edges1, bc = binned_statistic_dd(X, v, 'count', bins=3)
count1, edges1, bc = binned_statistic_dd(X, v, 'count', bins=3)
bc2 = np.array([63, 33, 86, 83, 88, 67, 57, 33, 42, 41, 82, 83, 92,
32, 36, 91, 43, 87, 81, 81])
@ -237,5 +235,4 @@ class TestBinnedStatistic(object):
if __name__ == "__main__":
#unittest.main()
run_module_suite()

@ -13,6 +13,8 @@ from wafo.stats.tests.common_tests import (check_normalization, check_moment,
check_entropy, check_private_entropy, NUMPY_BELOW_1_7,
check_edge_support, check_named_args)
from wafo.stats._distr_params import distcont
"""
Test all continuous distributions.
@ -26,98 +28,6 @@ not for numerically exact results.
DECIMAL = 5 # specify the precision of the tests # increased from 0 to 5
distcont = [
['alpha', (3.5704770516650459,)],
['anglit', ()],
['arcsine', ()],
['beta', (2.3098496451481823, 0.62687954300963677)],
['betaprime', (5, 6)],
['bradford', (0.29891359763170633,)],
['burr', (10.5, 4.3)],
['cauchy', ()],
['chi', (78,)],
['chi2', (55,)],
['cosine', ()],
['dgamma', (1.1023326088288166,)],
['dweibull', (2.0685080649914673,)],
['erlang', (10,)],
['expon', ()],
['exponpow', (2.697119160358469,)],
['exponweib', (2.8923945291034436, 1.9505288745913174)],
['f', (29, 18)],
['fatiguelife', (29,)], # correction numargs = 1
['fisk', (3.0857548622253179,)],
['foldcauchy', (4.7164673455831894,)],
['foldnorm', (1.9521253373555869,)],
['frechet_l', (3.6279911255583239,)],
['frechet_r', (1.8928171603534227,)],
['gamma', (1.9932305483800778,)],
['gausshyper', (13.763771604130699, 3.1189636648681431,
2.5145980350183019, 5.1811649903971615)], # veryslow
['genexpon', (9.1325976465418908, 16.231956600590632, 3.2819552690843983)],
['genextreme', (-0.1,)],
['gengamma', (4.4162385429431925, 3.1193091679242761)],
['genhalflogistic', (0.77274727809929322,)],
['genlogistic', (0.41192440799679475,)],
['genpareto', (0.1,)], # use case with finite moments
['gilbrat', ()],
['gompertz', (0.94743713075105251,)],
['gumbel_l', ()],
['gumbel_r', ()],
['halfcauchy', ()],
['halflogistic', ()],
['halfnorm', ()],
['hypsecant', ()],
['invgamma', (4.0668996136993067,)],
['invgauss', (0.14546264555347513,)],
['invweibull', (10.58,)],
['johnsonsb', (4.3172675099141058, 3.1837781130785063)],
['johnsonsu', (2.554395574161155, 2.2482281679651965)],
['ksone', (1000,)], # replace 22 by 100 to avoid failing range, ticket 956
['kstwobign', ()],
['laplace', ()],
['levy', ()],
['levy_l', ()],
# ['levy_stable', (0.35667405469844993,
# -0.67450531578494011)], #NotImplementedError
# rvs not tested
['loggamma', (0.41411931826052117,)],
['logistic', ()],
['loglaplace', (3.2505926592051435,)],
['lognorm', (0.95368226960575331,)],
['lomax', (1.8771398388773268,)],
['maxwell', ()],
['mielke', (10.4, 3.6)],
['nakagami', (4.9673794866666237,)],
['ncf', (27, 27, 0.41578441799226107)],
['nct', (14, 0.24045031331198066)],
['ncx2', (21, 1.0560465975116415)],
['norm', ()],
['pareto', (2.621716532144454,)],
['pearson3', (0.1,)],
['powerlaw', (1.6591133289905851,)],
['powerlognorm', (2.1413923530064087, 0.44639540782048337)],
['powernorm', (4.4453652254590779,)],
['rayleigh', ()],
['rdist', (0.9,)], # feels also slow
['recipinvgauss', (0.63004267809369119,)],
['reciprocal', (0.0062309367010521255, 1.0062309367010522)],
['rice', (0.7749725210111873,)],
['semicircular', ()],
['t', (2.7433514990818093,)],
['triang', (0.15785029824528218,)],
['truncexpon', (4.6907725456810478,)],
['truncnorm', (-1.0978730080013919, 2.7306754109031979)],
['truncnorm', (0.1, 2.)],
['tukeylambda', (3.1321477856738267,)],
['uniform', ()],
['vonmises', (3.9939042581071398,)],
['vonmises_line', (3.9939042581071398,)],
['wald', ()],
['weibull_max', (2.8687961709100187,)],
['weibull_min', (1.7866166930421596,)],
['wrapcauchy', (0.031071279018614728,)]]
## Last four of these fail all around. Need to be checked
distcont_extra = [
['betaprime', (100, 86)],
@ -159,7 +69,7 @@ distmissing = ['wald', 'gausshyper', 'genexpon', 'rv_continuous',
'johnsonsb', 'truncexpon', 'rice', 'invgauss', 'invgamma',
'powerlognorm']
distmiss = [[dist, args] for dist, args in distcont if dist in distmissing]
distmiss = [[dist,args] for dist,args in distcont if dist in distmissing]
distslow = ['rdist', 'gausshyper', 'recipinvgauss', 'ksone', 'genexpon',
'vonmises', 'vonmises_line', 'mielke', 'semicircular',
'cosine', 'invweibull', 'powerlognorm', 'johnsonsu', 'kstwobign']
@ -182,11 +92,12 @@ def _silence_fp_errors(func):
def test_cont_basic():
# this test skips slow distributions
with warnings.catch_warnings():
# warnings.filterwarnings('ignore',
# category=integrate.IntegrationWarning)
warnings.filterwarnings('ignore', category=integrate.IntegrationWarning)
for distname, arg in distcont[:]:
if distname in distslow:
continue
if distname is 'levy_stable':
continue
distfn = getattr(stats, distname)
np.random.seed(765456)
sn = 500
@ -231,19 +142,21 @@ def test_cont_basic():
yield knf(distname == 'truncnorm')(check_ppf_private), distfn, \
arg, distname
@npt.dec.slow
def test_cont_basic_slow():
# same as above for slow distributions
with warnings.catch_warnings():
# warnings.filterwarnings('ignore',
# category=integrate.IntegrationWarning)
warnings.filterwarnings('ignore', category=integrate.IntegrationWarning)
for distname, arg in distcont[:]:
if distname not in distslow:
continue
if distname is 'levy_stable':
continue
distfn = getattr(stats, distname)
np.random.seed(765456)
sn = 500
rvs = distfn.rvs(size=sn, *arg)
rvs = distfn.rvs(size=sn,*arg)
sm = rvs.mean()
sv = rvs.var()
m, v = distfn.stats(*arg)
@ -287,12 +200,13 @@ def test_cont_basic_slow():
@npt.dec.slow
def test_moments():
with warnings.catch_warnings():
# warnings.filterwarnings('ignore',
# category=integrate.IntegrationWarning)
warnings.filterwarnings('ignore', category=integrate.IntegrationWarning)
knf = npt.dec.knownfailureif
fail_normalization = set(['vonmises', 'ksone'])
fail_higher = set(['vonmises', 'ksone', 'ncf'])
for distname, arg in distcont[:]:
if distname is 'levy_stable':
continue
distfn = getattr(stats, distname)
m, v, s, k = distfn.stats(*arg, moments='mvsk')
cond1, cond2 = distname in fail_normalization, distname in fail_higher
@ -316,45 +230,44 @@ def check_sample_meanvar_(distfn, arg, m, v, sm, sv, sn, msg):
check_sample_var(sv, sn, v)
def check_sample_mean(sm, v, n, popmean):
def check_sample_mean(sm,v,n, popmean):
# from stats.stats.ttest_1samp(a, popmean):
# Calculates the t-obtained for the independent samples T-test on ONE group
# of scores a, given a population mean.
#
# Returns: t-value, two-tailed prob
df = n - 1
svar = ((n - 1) * v) / float(df) # looks redundant
t = (sm - popmean) / np.sqrt(svar * (1.0 / n))
prob = stats.betai(0.5 * df, 0.5, df / (df + t * t))
df = n-1
svar = ((n-1)*v) / float(df) # looks redundant
t = (sm-popmean) / np.sqrt(svar*(1.0/n))
prob = stats.betai(0.5*df, 0.5, df/(df+t*t))
# return t,prob
npt.assert_(prob > 0.01, 'mean fail, t,prob = %f, %f, m, sm=%f,%f' %
(t, prob, popmean, sm))
def check_sample_var(sv, n, popvar):
# two-sided chisquare test for sample variance equal to hypothesized
# variance
df = n - 1
chi2 = (n - 1) * popvar / float(popvar)
pval = stats.chisqprob(chi2, df) * 2
def check_sample_var(sv,n, popvar):
# two-sided chisquare test for sample variance equal to hypothesized variance
df = n-1
chi2 = (n-1)*popvar/float(popvar)
pval = stats.chisqprob(chi2,df)*2
npt.assert_(pval > 0.01, 'var fail, t, pval = %f, %f, v, sv=%f, %f' %
(chi2, pval, popvar, sv))
(chi2,pval,popvar,sv))
def check_cdf_ppf(distfn, arg, msg):
def check_cdf_ppf(distfn,arg,msg):
values = [0.001, 0.5, 0.999]
npt.assert_almost_equal(distfn.cdf(distfn.ppf(values, *arg), *arg),
values, decimal=DECIMAL, err_msg=msg +
' - cdf-ppf roundtrip')
def check_sf_isf(distfn, arg, msg):
npt.assert_almost_equal(distfn.sf(distfn.isf([0.1, 0.5, 0.9], *arg), *arg),
[0.1, 0.5, 0.9], decimal=DECIMAL, err_msg=msg +
def check_sf_isf(distfn,arg,msg):
npt.assert_almost_equal(distfn.sf(distfn.isf([0.1,0.5,0.9], *arg), *arg),
[0.1,0.5,0.9], decimal=DECIMAL, err_msg=msg +
' - sf-isf roundtrip')
npt.assert_almost_equal(distfn.cdf([0.1, 0.9], *arg),
1.0 - distfn.sf([0.1, 0.9], *arg),
npt.assert_almost_equal(distfn.cdf([0.1,0.9], *arg),
1.0-distfn.sf([0.1,0.9], *arg),
decimal=DECIMAL, err_msg=msg +
' - cdf-sf relationship')
@ -365,16 +278,15 @@ def check_pdf(distfn, arg, msg):
eps = 1e-6
pdfv = distfn.pdf(median, *arg)
if (pdfv < 1e-4) or (pdfv > 1e4):
# avoid checking a case where pdf is close to zero or huge
# (singularity)
# avoid checking a case where pdf is close to zero or huge (singularity)
median = median + 0.1
pdfv = distfn.pdf(median, *arg)
cdfdiff = (distfn.cdf(median + eps, *arg) -
distfn.cdf(median - eps, *arg)) / eps / 2.0
distfn.cdf(median - eps, *arg))/eps/2.0
# replace with better diff and better test (more points),
# actually, this works pretty well
npt.assert_almost_equal(pdfv, cdfdiff, decimal=DECIMAL,
err_msg=msg + ' - cdf-pdf relationship')
npt.assert_almost_equal(pdfv, cdfdiff,
decimal=DECIMAL, err_msg=msg + ' - cdf-pdf relationship')
def check_pdf_logpdf(distfn, args, msg):
@ -385,8 +297,7 @@ def check_pdf_logpdf(distfn, args, msg):
logpdf = distfn.logpdf(vals, *args)
pdf = pdf[pdf != 0]
logpdf = logpdf[np.isfinite(logpdf)]
npt.assert_almost_equal(np.log(pdf), logpdf, decimal=7,
err_msg=msg + " - logpdf-log(pdf) relationship")
npt.assert_almost_equal(np.log(pdf), logpdf, decimal=7, err_msg=msg + " - logpdf-log(pdf) relationship")
def check_sf_logsf(distfn, args, msg):
@ -397,8 +308,7 @@ def check_sf_logsf(distfn, args, msg):
logsf = distfn.logsf(vals, *args)
sf = sf[sf != 0]
logsf = logsf[np.isfinite(logsf)]
npt.assert_almost_equal(np.log(sf), logsf, decimal=7,
err_msg=msg + " - logsf-log(sf) relationship")
npt.assert_almost_equal(np.log(sf), logsf, decimal=7, err_msg=msg + " - logsf-log(sf) relationship")
def check_cdf_logcdf(distfn, args, msg):
@ -409,16 +319,15 @@ def check_cdf_logcdf(distfn, args, msg):
logcdf = distfn.logcdf(vals, *args)
cdf = cdf[cdf != 0]
logcdf = logcdf[np.isfinite(logcdf)]
npt.assert_almost_equal(np.log(cdf), logcdf, decimal=7,
err_msg=msg + " - logcdf-log(cdf) relationship")
npt.assert_almost_equal(np.log(cdf), logcdf, decimal=7, err_msg=msg + " - logcdf-log(cdf) relationship")
def check_distribution_rvs(dist, args, alpha, rvs):
# test from scipy.stats.tests
# this version reuses existing random variables
D, pval = stats.kstest(rvs, dist, args=args, N=1000)
D,pval = stats.kstest(rvs, dist, args=args, N=1000)
if (pval < alpha):
D, pval = stats.kstest(dist, '', args=args, N=1000)
D,pval = stats.kstest(dist,'',args=args, N=1000)
npt.assert_(pval > alpha, "D = " + str(D) + "; pval = " + str(pval) +
"; alpha = " + str(alpha) + "\nargs = " + str(args))
@ -431,12 +340,12 @@ def check_vecentropy(distfn, args):
def check_loc_scale(distfn, arg, m, v, msg):
loc, scale = 10.0, 10.0
mt, vt = distfn.stats(loc=loc, scale=scale, *arg)
npt.assert_allclose(m * scale + loc, mt)
npt.assert_allclose(v * scale * scale, vt)
npt.assert_allclose(m*scale + loc, mt)
npt.assert_allclose(v*scale*scale, vt)
def check_ppf_private(distfn, arg, msg):
# fails by design for truncnorm self.nb not defined
#fails by design for truncnorm self.nb not defined
ppfs = distfn._ppf(np.array([0.1, 0.5, 0.9]), *arg)
npt.assert_(not np.any(np.isnan(ppfs)), msg + 'ppf private is nan')

@ -2,37 +2,17 @@ from __future__ import division, print_function, absolute_import
import numpy.testing as npt
import numpy as np
try:
from wafo.stats.six import xrange
except:
pass
from scipy.lib.six import xrange
from wafo import stats
from wafo.stats.tests.common_tests import (check_normalization, check_moment,
check_mean_expect,
check_var_expect, check_skew_expect, check_kurt_expect,
check_entropy, check_private_entropy, check_edge_support,
check_named_args)
from wafo.stats._distr_params import distdiscrete
knf = npt.dec.knownfailureif
distdiscrete = [
['bernoulli', (0.3, )],
['binom', (5, 0.4)],
['boltzmann', (1.4, 19)],
['dlaplace', (0.8,)], # 0.5
['geom', (0.5,)],
['hypergeom', (30, 12, 6)],
['hypergeom', (21, 3, 12)], # numpy.random (3,18,12) numpy ticket:921
['hypergeom', (21, 18, 11)], # numpy.random (18,3,11) numpy ticket:921
['logser', (0.6,)], # reenabled, numpy ticket:921
['nbinom', (5, 0.5)],
['nbinom', (0.4, 0.4)], # from tickets: 583
['planck', (0.51,)], # 4.1
['poisson', (0.6,)],
['randint', (7, 31)],
['skellam', (15, 8)],
['zipf', (6.5,)]
]
def test_discrete_basic():
for distname, arg in distdiscrete:
@ -40,7 +20,7 @@ def test_discrete_basic():
np.random.seed(9765456)
rvs = distfn.rvs(size=2000, *arg)
supp = np.unique(rvs)
#_m, v = distfn.stats(*arg)
m, v = distfn.stats(*arg)
yield check_cdf_ppf, distfn, arg, supp, distname + ' cdf_ppf'
yield check_pmf_cdf, distfn, arg, distname
@ -56,7 +36,7 @@ def test_discrete_basic():
if distname in seen:
continue
seen.add(distname)
distfn = getattr(stats, distname)
distfn = getattr(stats,distname)
locscale_defaults = (0,)
meths = [distfn.pmf, distfn.logpmf, distfn.cdf, distfn.logcdf,
distfn.logsf]
@ -74,7 +54,7 @@ def test_discrete_basic():
def test_moments():
for distname, arg in distdiscrete:
distfn = getattr(stats, distname)
distfn = getattr(stats,distname)
m, v, s, k = distfn.stats(*arg, moments='mvsk')
yield check_normalization, distfn, arg, distname
@ -84,13 +64,13 @@ def test_moments():
yield check_var_expect, distfn, arg, m, v, distname
yield check_skew_expect, distfn, arg, m, v, s, distname
cond = distname in ['zipf']
cond = False #distname in ['zipf']
msg = distname + ' fails kurtosis'
yield knf(cond, msg)(check_kurt_expect), distfn, arg, m, v, k, distname
# frozen distr moments
yield check_moment_frozen, distfn, arg, m, 1
yield check_moment_frozen, distfn, arg, v + m * m, 2
yield check_moment_frozen, distfn, arg, v+m*m, 2
def check_cdf_ppf(distfn, arg, supp, msg):
@ -108,7 +88,7 @@ def check_cdf_ppf(distfn, arg, supp, msg):
def check_pmf_cdf(distfn, arg, distname):
startind = np.int(distfn.ppf(0.01, *arg) - 1)
index = list(range(startind, startind + 10))
cdfs, pmfs_cum = distfn.cdf(index, *arg), distfn.pmf(index, *arg).cumsum()
cdfs, pmfs_cum = distfn.cdf(index,*arg), distfn.pmf(index, *arg).cumsum()
atol, rtol = 1e-10, 1e-10
if distname == 'skellam': # ncx2 accuracy
@ -158,7 +138,7 @@ def check_discrete_chisquare(distfn, arg, rvs, alpha, msg):
"""
n = len(rvs)
nsupp = 20
wsupp = 1.0 / nsupp
wsupp = 1.0/nsupp
# construct intervals with minimum mass 1/nsupp
# intervals are left-half-open as in a cdf difference
@ -167,30 +147,30 @@ def check_discrete_chisquare(distfn, arg, rvs, alpha, msg):
distsupp = [max(distfn.a, -1000)]
distmass = []
for ii in distsupport:
current = distfn.cdf(ii, *arg)
if current - last >= wsupp - 1e-14:
current = distfn.cdf(ii,*arg)
if current - last >= wsupp-1e-14:
distsupp.append(ii)
distmass.append(current - last)
last = current
if current > (1 - wsupp):
if current > (1-wsupp):
break
if distsupp[-1] < distfn.b:
distsupp.append(distfn.b)
distmass.append(1 - last)
distmass.append(1-last)
distsupp = np.array(distsupp)
distmass = np.array(distmass)
# convert intervals to right-half-open as required by histogram
histsupp = distsupp + 1e-8
histsupp = distsupp+1e-8
histsupp[0] = distfn.a
# find sample frequencies and perform chisquare test
freq, _hsupp = np.histogram(rvs, histsupp)
#cdfs = distfn.cdf(distsupp, *arg)
(_chis, pval) = stats.chisquare(np.array(freq), n * distmass)
freq,hsupp = np.histogram(rvs,histsupp)
cdfs = distfn.cdf(distsupp,*arg)
(chis,pval) = stats.chisquare(np.array(freq),n*distmass)
npt.assert_(pval > alpha, 'chisquare - test for %s'
' at arg = %s with pval = %s' % (msg, str(arg), str(pval)))
' at arg = %s with pval = %s' % (msg,str(arg),str(pval)))
def check_scale_docstring(distfn):

File diff suppressed because it is too large Load Diff

@ -33,6 +33,7 @@ failing_fits = [
'tukeylambda',
'vonmises',
'wrapcauchy',
'levy_stable'
]
# Don't run the fit test on these:
@ -45,14 +46,15 @@ skip_fit = [
def test_cont_fit():
# this tests the closeness of the estimated parameters to the true
# parameters with fit method of continuous distributions
# Note: slow, some distributions don't converge with sample size <= 10000
# Note: is slow, some distributions don't converge with sample size <= 10000
for distname, arg in distcont:
if distname not in skip_fit:
yield check_cont_fit, distname, arg
yield check_cont_fit, distname,arg
def check_cont_fit(distname, arg):
def check_cont_fit(distname,arg):
options = dict(method='mps', floc=0.)
if distname in failing_fits:
# Skip failing fits unless overridden
xfail = True
@ -62,16 +64,18 @@ def check_cont_fit(distname, arg):
pass
if xfail:
msg = "Fitting %s doesn't work reliably yet" % distname
msg += " [Set environment variable SCIPY_XFAIL=1 to run this " + \
"test nevertheless.]"
dec.knownfailureif(True, msg)(lambda: None)()
msg += " [Set environment variable SCIPY_XFAIL=1 to run this test nevertheless.]"
#dec.knownfailureif(True, msg)(lambda: None)()
options['floc']=0.
options['fscale']=1.
# print('Testing %s' % distname)
distfn = getattr(stats, distname)
truearg = np.hstack([arg, [0.0, 1.0]])
diffthreshold = np.max(np.vstack([
truearg * thresh_percent,
np.ones(distfn.numargs + 2) * thresh_min]), 0)
truearg = np.hstack([arg,[0.0,1.0]])
diffthreshold = np.max(np.vstack([truearg*thresh_percent,
np.ones(distfn.numargs+2)*thresh_min]),0)
for fit_size in fit_sizes:
# Note that if a fit succeeds, the other fit_sizes are skipped
@ -79,16 +83,17 @@ def check_cont_fit(distname, arg):
with np.errstate(all='ignore'):
rvs = distfn.rvs(size=fit_size, *arg)
#phat = distfn.fit2(rvs)
phat = distfn.fit2(rvs, method='mps')
# phat = distfn.fit2(rvs)
phat = distfn.fit2(rvs, **options)
est = phat.par
#est = distfn.fit(rvs) # start with default values
diff = est - truearg
# threshold for location
diffthreshold[-2] = np.max([np.abs(rvs.mean()) * thresh_percent,
thresh_min])
diffthreshold[-2] = np.max([np.abs(rvs.mean())*thresh_percent,thresh_min])
if np.any(np.isnan(est)):
raise AssertionError('nan returned in fit')

@ -180,5 +180,23 @@ def test_kde_integer_input():
assert_array_almost_equal(kde(x1), y_expected, decimal=6)
def test_pdf_logpdf():
np.random.seed(1)
n_basesample = 50
xn = np.random.randn(n_basesample)
# Default
gkde = stats.gaussian_kde(xn)
xs = np.linspace(-15, 12, 25)
pdf = gkde.evaluate(xs)
pdf2 = gkde.pdf(xs)
assert_almost_equal(pdf, pdf2, decimal=12)
logpdf = np.log(pdf)
logpdf2 = gkde.logpdf(xs)
assert_almost_equal(logpdf, logpdf2, decimal=12)
if __name__ == "__main__":
run_module_suite()

@ -9,9 +9,8 @@ import warnings
import numpy as np
from numpy.random import RandomState
from numpy.testing import (TestCase, run_module_suite, assert_array_equal,
assert_almost_equal, assert_array_less,
assert_array_almost_equal, assert_raises, assert_,
assert_allclose, assert_equal, dec)
assert_almost_equal, assert_array_less, assert_array_almost_equal,
assert_raises, assert_, assert_allclose, assert_equal, dec, assert_warns)
from wafo import stats
@ -37,20 +36,19 @@ g10 = [0.991, 0.995, 0.984, 0.994, 0.997, 0.997, 0.991, 0.998, 1.004, 0.997]
class TestShapiro(TestCase):
def test_basic(self):
x1 = [0.11, 7.87, 4.61, 10.14, 7.95, 3.14, 0.46,
4.43, 0.21, 4.75, 0.71, 1.52, 3.24,
0.93, 0.42, 4.97, 9.53, 4.55, 0.47, 6.66]
w, pw = stats.shapiro(x1)
assert_almost_equal(w, 0.90047299861907959, 6)
assert_almost_equal(pw, 0.042089745402336121, 6)
x2 = [1.36, 1.14, 2.92, 2.55, 1.46, 1.06, 5.27, -1.11,
3.48, 1.10, 0.88, -0.51, 1.46, 0.52, 6.20, 1.69,
0.08, 3.67, 2.81, 3.49]
w, pw = stats.shapiro(x2)
assert_almost_equal(w, 0.9590270, 6)
assert_almost_equal(pw, 0.52460, 3)
x1 = [0.11,7.87,4.61,10.14,7.95,3.14,0.46,
4.43,0.21,4.75,0.71,1.52,3.24,
0.93,0.42,4.97,9.53,4.55,0.47,6.66]
w,pw = stats.shapiro(x1)
assert_almost_equal(w,0.90047299861907959,6)
assert_almost_equal(pw,0.042089745402336121,6)
x2 = [1.36,1.14,2.92,2.55,1.46,1.06,5.27,-1.11,
3.48,1.10,0.88,-0.51,1.46,0.52,6.20,1.69,
0.08,3.67,2.81,3.49]
w,pw = stats.shapiro(x2)
assert_almost_equal(w,0.9590270,6)
assert_almost_equal(pw,0.52460,3)
def test_bad_arg(self):
# Length of x is less than 3.
@ -59,25 +57,24 @@ class TestShapiro(TestCase):
class TestAnderson(TestCase):
def test_normal(self):
rs = RandomState(1234567890)
x1 = rs.standard_exponential(size=50)
x2 = rs.standard_normal(size=50)
A, crit, _sig = stats.anderson(x1)
A,crit,sig = stats.anderson(x1)
assert_array_less(crit[:-1], A)
A, crit, _sig = stats.anderson(x2)
A,crit,sig = stats.anderson(x2)
assert_array_less(A, crit[-2:])
def test_expon(self):
rs = RandomState(1234567890)
x1 = rs.standard_exponential(size=50)
x2 = rs.standard_normal(size=50)
A, crit, _sig = stats.anderson(x1, 'expon')
A,crit,sig = stats.anderson(x1,'expon')
assert_array_less(A, crit[-2:])
olderr = np.seterr(all='ignore')
try:
A, crit, _sig = stats.anderson(x2, 'expon')
A,crit,sig = stats.anderson(x2,'expon')
finally:
np.seterr(**olderr)
assert_(A > crit[-1])
@ -86,34 +83,150 @@ class TestAnderson(TestCase):
assert_raises(ValueError, stats.anderson, [1], dist='plate_of_shrimp')
class TestAndersonKSamp(TestCase):
def test_example1a(self):
# Example data from Scholz & Stephens (1987), originally
# published in Lehmann (1995, Nonparametrics, Statistical
# Methods Based on Ranks, p. 309)
# Pass a mixture of lists and arrays
t1 = [38.7, 41.5, 43.8, 44.5, 45.5, 46.0, 47.7, 58.0]
t2 = np.array([39.2, 39.3, 39.7, 41.4, 41.8, 42.9, 43.3, 45.8])
t3 = np.array([34.0, 35.0, 39.0, 40.0, 43.0, 43.0, 44.0, 45.0])
t4 = np.array([34.0, 34.8, 34.8, 35.4, 37.2, 37.8, 41.2, 42.8])
assert_warns(UserWarning, stats.anderson_ksamp, (t1, t2, t3, t4),
midrank=False)
with warnings.catch_warnings():
warnings.filterwarnings('ignore', message='approximate p-value')
Tk, tm, p = stats.anderson_ksamp((t1, t2, t3, t4), midrank=False)
assert_almost_equal(Tk, 4.449, 3)
assert_array_almost_equal([0.4985, 1.3237, 1.9158, 2.4930, 3.2459],
tm, 4)
assert_almost_equal(p, 0.0021, 4)
def test_example1b(self):
# Example data from Scholz & Stephens (1987), originally
# published in Lehmann (1995, Nonparametrics, Statistical
# Methods Based on Ranks, p. 309)
# Pass arrays
t1 = np.array([38.7, 41.5, 43.8, 44.5, 45.5, 46.0, 47.7, 58.0])
t2 = np.array([39.2, 39.3, 39.7, 41.4, 41.8, 42.9, 43.3, 45.8])
t3 = np.array([34.0, 35.0, 39.0, 40.0, 43.0, 43.0, 44.0, 45.0])
t4 = np.array([34.0, 34.8, 34.8, 35.4, 37.2, 37.8, 41.2, 42.8])
with warnings.catch_warnings():
warnings.filterwarnings('ignore', message='approximate p-value')
Tk, tm, p = stats.anderson_ksamp((t1, t2, t3, t4), midrank=True)
assert_almost_equal(Tk, 4.480, 3)
assert_array_almost_equal([0.4985, 1.3237, 1.9158, 2.4930, 3.2459],
tm, 4)
assert_almost_equal(p, 0.0020, 4)
def test_example2a(self):
# Example data taken from an earlier technical report of
# Scholz and Stephens
# Pass lists instead of arrays
t1 = [194, 15, 41, 29, 33, 181]
t2 = [413, 14, 58, 37, 100, 65, 9, 169, 447, 184, 36, 201, 118]
t3 = [34, 31, 18, 18, 67, 57, 62, 7, 22, 34]
t4 = [90, 10, 60, 186, 61, 49, 14, 24, 56, 20, 79, 84, 44, 59, 29,
118, 25, 156, 310, 76, 26, 44, 23, 62]
t5 = [130, 208, 70, 101, 208]
t6 = [74, 57, 48, 29, 502, 12, 70, 21, 29, 386, 59, 27]
t7 = [55, 320, 56, 104, 220, 239, 47, 246, 176, 182, 33]
t8 = [23, 261, 87, 7, 120, 14, 62, 47, 225, 71, 246, 21, 42, 20, 5,
12, 120, 11, 3, 14, 71, 11, 14, 11, 16, 90, 1, 16, 52, 95]
t9 = [97, 51, 11, 4, 141, 18, 142, 68, 77, 80, 1, 16, 106, 206, 82,
54, 31, 216, 46, 111, 39, 63, 18, 191, 18, 163, 24]
t10 = [50, 44, 102, 72, 22, 39, 3, 15, 197, 188, 79, 88, 46, 5, 5, 36,
22, 139, 210, 97, 30, 23, 13, 14]
t11 = [359, 9, 12, 270, 603, 3, 104, 2, 438]
t12 = [50, 254, 5, 283, 35, 12]
t13 = [487, 18, 100, 7, 98, 5, 85, 91, 43, 230, 3, 130]
t14 = [102, 209, 14, 57, 54, 32, 67, 59, 134, 152, 27, 14, 230, 66,
61, 34]
with warnings.catch_warnings():
warnings.filterwarnings('ignore', message='approximate p-value')
Tk, tm, p = stats.anderson_ksamp((t1, t2, t3, t4, t5, t6, t7, t8,
t9, t10, t11, t12, t13, t14),
midrank=False)
assert_almost_equal(Tk, 3.288, 3)
assert_array_almost_equal([0.5990, 1.3269, 1.8052, 2.2486, 2.8009],
tm, 4)
assert_almost_equal(p, 0.0041, 4)
def test_example2b(self):
# Example data taken from an earlier technical report of
# Scholz and Stephens
t1 = [194, 15, 41, 29, 33, 181]
t2 = [413, 14, 58, 37, 100, 65, 9, 169, 447, 184, 36, 201, 118]
t3 = [34, 31, 18, 18, 67, 57, 62, 7, 22, 34]
t4 = [90, 10, 60, 186, 61, 49, 14, 24, 56, 20, 79, 84, 44, 59, 29,
118, 25, 156, 310, 76, 26, 44, 23, 62]
t5 = [130, 208, 70, 101, 208]
t6 = [74, 57, 48, 29, 502, 12, 70, 21, 29, 386, 59, 27]
t7 = [55, 320, 56, 104, 220, 239, 47, 246, 176, 182, 33]
t8 = [23, 261, 87, 7, 120, 14, 62, 47, 225, 71, 246, 21, 42, 20, 5,
12, 120, 11, 3, 14, 71, 11, 14, 11, 16, 90, 1, 16, 52, 95]
t9 = [97, 51, 11, 4, 141, 18, 142, 68, 77, 80, 1, 16, 106, 206, 82,
54, 31, 216, 46, 111, 39, 63, 18, 191, 18, 163, 24]
t10 = [50, 44, 102, 72, 22, 39, 3, 15, 197, 188, 79, 88, 46, 5, 5, 36,
22, 139, 210, 97, 30, 23, 13, 14]
t11 = [359, 9, 12, 270, 603, 3, 104, 2, 438]
t12 = [50, 254, 5, 283, 35, 12]
t13 = [487, 18, 100, 7, 98, 5, 85, 91, 43, 230, 3, 130]
t14 = [102, 209, 14, 57, 54, 32, 67, 59, 134, 152, 27, 14, 230, 66,
61, 34]
with warnings.catch_warnings():
warnings.filterwarnings('ignore', message='approximate p-value')
Tk, tm, p = stats.anderson_ksamp((t1, t2, t3, t4, t5, t6, t7, t8,
t9, t10, t11, t12, t13, t14),
midrank=True)
assert_almost_equal(Tk, 3.294, 3)
assert_array_almost_equal([0.5990, 1.3269, 1.8052, 2.2486, 2.8009],
tm, 4)
assert_almost_equal(p, 0.0041, 4)
def test_not_enough_samples(self):
assert_raises(ValueError, stats.anderson_ksamp, np.ones(5))
def test_no_distinct_observations(self):
assert_raises(ValueError, stats.anderson_ksamp,
(np.ones(5), np.ones(5)))
def test_empty_sample(self):
assert_raises(ValueError, stats.anderson_ksamp, (np.ones(5), []))
class TestAnsari(TestCase):
def test_small(self):
x = [1, 2, 3, 3, 4]
y = [3, 2, 6, 1, 6, 1, 4, 1]
W, pval = stats.ansari(x, y)
assert_almost_equal(W, 23.5, 11)
assert_almost_equal(pval, 0.13499256881897437, 11)
x = [1,2,3,3,4]
y = [3,2,6,1,6,1,4,1]
W, pval = stats.ansari(x,y)
assert_almost_equal(W,23.5,11)
assert_almost_equal(pval,0.13499256881897437,11)
def test_approx(self):
ramsay = np.array((111, 107, 100, 99, 102, 106, 109, 108, 104, 99,
101, 96, 97, 102, 107, 113, 116, 113, 110, 98))
parekh = np.array((107, 108, 106, 98, 105, 103, 110, 105, 104, 100,
96, 108, 103, 104, 114, 114, 113, 108, 106, 99))
parekh = np.array((107, 108, 106, 98, 105, 103, 110, 105, 104,
100, 96, 108, 103, 104, 114, 114, 113, 108, 106, 99))
with warnings.catch_warnings():
warnings.filterwarnings('ignore',
message="Ties preclude use of exact " +
"statistic.")
message="Ties preclude use of exact statistic.")
W, pval = stats.ansari(ramsay, parekh)
assert_almost_equal(W, 185.5, 11)
assert_almost_equal(pval, 0.18145819972867083, 11)
assert_almost_equal(W,185.5,11)
assert_almost_equal(pval,0.18145819972867083,11)
def test_exact(self):
W, pval = stats.ansari([1, 2, 3, 4], [15, 5, 20, 8, 10, 12])
assert_almost_equal(W, 10.0, 11)
assert_almost_equal(pval, 0.533333333333333333, 7)
W,pval = stats.ansari([1,2,3,4],[15,5,20,8,10,12])
assert_almost_equal(W,10.0,11)
assert_almost_equal(pval,0.533333333333333333,7)
def test_bad_arg(self):
assert_raises(ValueError, stats.ansari, [], [1])
@ -125,8 +238,8 @@ class TestBartlett(TestCase):
def test_data(self):
args = [g1, g2, g3, g4, g5, g6, g7, g8, g9, g10]
T, pval = stats.bartlett(*args)
assert_almost_equal(T, 20.78587342806484, 7)
assert_almost_equal(pval, 0.0136358632781, 7)
assert_almost_equal(T,20.78587342806484,7)
assert_almost_equal(pval,0.0136358632781,7)
def test_bad_arg(self):
# Too few args raises ValueError.
@ -138,15 +251,14 @@ class TestLevene(TestCase):
def test_data(self):
args = [g1, g2, g3, g4, g5, g6, g7, g8, g9, g10]
W, pval = stats.levene(*args)
assert_almost_equal(W, 1.7059176930008939, 7)
assert_almost_equal(pval, 0.0990829755522, 7)
assert_almost_equal(W,1.7059176930008939,7)
assert_almost_equal(pval,0.0990829755522,7)
def test_trimmed1(self):
# Test that center='trimmed' gives the same result as center='mean'
# when proportiontocut=0.
W1, pval1 = stats.levene(g1, g2, g3, center='mean')
W2, pval2 = stats.levene(
g1, g2, g3, center='trimmed', proportiontocut=0.0)
W2, pval2 = stats.levene(g1, g2, g3, center='trimmed', proportiontocut=0.0)
assert_almost_equal(W1, W2)
assert_almost_equal(pval1, pval2)
@ -157,10 +269,8 @@ class TestLevene(TestCase):
x2 = np.random.permutation(x)
# Use center='trimmed'
W0, _pval0 = stats.levene(x, y, center='trimmed',
proportiontocut=0.125)
W1, pval1 = stats.levene(
x2, y, center='trimmed', proportiontocut=0.125)
W0, pval0 = stats.levene(x, y, center='trimmed', proportiontocut=0.125)
W1, pval1 = stats.levene(x2, y, center='trimmed', proportiontocut=0.125)
# Trim the data here, and use center='mean'
W2, pval2 = stats.levene(x[1:-1], y[1:-1], center='mean')
# Result should be the same.
@ -169,21 +279,21 @@ class TestLevene(TestCase):
assert_almost_equal(pval1, pval2)
def test_equal_mean_median(self):
x = np.linspace(-1, 1, 21)
x = np.linspace(-1,1,21)
np.random.seed(1234)
x2 = np.random.permutation(x)
y = x ** 3
y = x**3
W1, pval1 = stats.levene(x, y, center='mean')
W2, pval2 = stats.levene(x2, y, center='median')
assert_almost_equal(W1, W2)
assert_almost_equal(pval1, pval2)
def test_bad_keyword(self):
x = np.linspace(-1, 1, 21)
x = np.linspace(-1,1,21)
assert_raises(TypeError, stats.levene, x, x, portiontocut=0.1)
def test_bad_center_value(self):
x = np.linspace(-1, 1, 21)
x = np.linspace(-1,1,21)
assert_raises(ValueError, stats.levene, x, x, center='trim')
def test_too_few_args(self):
@ -193,16 +303,16 @@ class TestLevene(TestCase):
class TestBinomP(TestCase):
def test_data(self):
pval = stats.binom_test(100, 250)
assert_almost_equal(pval, 0.0018833009350757682, 11)
pval = stats.binom_test(201, 405)
assert_almost_equal(pval, 0.92085205962670713, 11)
pval = stats.binom_test([682, 243], p=3.0 / 4)
assert_almost_equal(pval, 0.38249155957481695, 11)
pval = stats.binom_test(100,250)
assert_almost_equal(pval,0.0018833009350757682,11)
pval = stats.binom_test(201,405)
assert_almost_equal(pval,0.92085205962670713,11)
pval = stats.binom_test([682,243],p=3.0/4)
assert_almost_equal(pval,0.38249155957481695,11)
def test_bad_len_x(self):
# Length of x must be 1 or 2.
assert_raises(ValueError, stats.binom_test, [1, 2, 3])
assert_raises(ValueError, stats.binom_test, [1,2,3])
def test_bad_n(self):
# len(x) is 1, but n is invalid.
@ -218,10 +328,10 @@ class TestBinomP(TestCase):
class TestFindRepeats(TestCase):
def test_basic(self):
a = [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 5]
res, nums = stats.find_repeats(a)
assert_array_equal(res, [1, 2, 3, 4])
assert_array_equal(nums, [3, 3, 2, 2])
a = [1,2,3,4,1,2,3,4,1,2,5]
res,nums = stats.find_repeats(a)
assert_array_equal(res,[1,2,3,4])
assert_array_equal(nums,[3,3,2,2])
def test_empty_result(self):
# Check that empty arrays are returned when there are no repeats.
@ -236,16 +346,14 @@ class TestFligner(TestCase):
def test_data(self):
# numbers from R: fligner.test in package stats
x1 = np.arange(5)
assert_array_almost_equal(stats.fligner(x1, x1 ** 2),
(3.2282229927203536, 0.072379187848207877),
11)
assert_array_almost_equal(stats.fligner(x1,x1**2),
(3.2282229927203536, 0.072379187848207877), 11)
def test_trimmed1(self):
# Test that center='trimmed' gives the same result as center='mean'
# when proportiontocut=0.
Xsq1, pval1 = stats.fligner(g1, g2, g3, center='mean')
Xsq2, pval2 = stats.fligner(
g1, g2, g3, center='trimmed', proportiontocut=0.0)
Xsq2, pval2 = stats.fligner(g1, g2, g3, center='trimmed', proportiontocut=0.0)
assert_almost_equal(Xsq1, Xsq2)
assert_almost_equal(pval1, pval2)
@ -253,8 +361,7 @@ class TestFligner(TestCase):
x = [1.2, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 100.0]
y = [0.0, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 200.0]
# Use center='trimmed'
Xsq1, pval1 = stats.fligner(
x, y, center='trimmed', proportiontocut=0.125)
Xsq1, pval1 = stats.fligner(x, y, center='trimmed', proportiontocut=0.125)
# Trim the data here, and use center='mean'
Xsq2, pval2 = stats.fligner(x[1:-1], y[1:-1], center='mean')
# Result should be the same.
@ -267,7 +374,7 @@ class TestFligner(TestCase):
# errors) there are not. This difference leads to differences in the
# third significant digit of W.
#
# def test_equal_mean_median(self):
#def test_equal_mean_median(self):
# x = np.linspace(-1,1,21)
# y = x**3
# W1, pval1 = stats.fligner(x, y, center='mean')
@ -276,11 +383,11 @@ class TestFligner(TestCase):
# assert_almost_equal(pval1, pval2)
def test_bad_keyword(self):
x = np.linspace(-1, 1, 21)
x = np.linspace(-1,1,21)
assert_raises(TypeError, stats.fligner, x, x, portiontocut=0.1)
def test_bad_center_value(self):
x = np.linspace(-1, 1, 21)
x = np.linspace(-1,1,21)
assert_raises(ValueError, stats.fligner, x, x, center='trim')
def test_bad_num_args(self):
@ -289,13 +396,11 @@ class TestFligner(TestCase):
class TestMood(TestCase):
def test_mood(self):
# numbers from R: mood.test in package stats
x1 = np.arange(5)
assert_array_almost_equal(stats.mood(x1, x1 ** 2),
(-1.3830857299399906, 0.16663858066771478),
11)
assert_array_almost_equal(stats.mood(x1, x1**2),
(-1.3830857299399906, 0.16663858066771478), 11)
def test_mood_order_of_args(self):
# z should change sign when the order of arguments changes, pvalue
@ -308,7 +413,7 @@ class TestMood(TestCase):
assert_array_almost_equal([z1, p1], [-z2, p2])
def test_mood_with_axis_none(self):
# Test with axis = None, compare with results from R
#Test with axis = None, compare with results from R
x1 = [-0.626453810742332, 0.183643324222082, -0.835628612410047,
1.59528080213779, 0.329507771815361, -0.820468384118015,
0.487429052428485, 0.738324705129217, 0.575781351653492,
@ -387,8 +492,7 @@ class TestMood(TestCase):
stats.mood(slice1, slice2))
def test_mood_bad_arg(self):
# Raise ValueError when the sum of the lengths of the args is less than
# 3
# Raise ValueError when the sum of the lengths of the args is less than 3
assert_raises(ValueError, stats.mood, [1], [])
@ -406,7 +510,7 @@ class TestProbplot(TestCase):
assert_allclose(osr, np.sort(x))
assert_allclose(osm, osm_expected)
_res, res_fit = stats.probplot(x, fit=True)
res, res_fit = stats.probplot(x, fit=True)
res_fit_expected = [1.05361841, 0.31297795, 0.98741609]
assert_allclose(res_fit, res_fit_expected)
@ -423,7 +527,7 @@ class TestProbplot(TestCase):
assert_allclose(osr1, osr2)
assert_allclose(osr1, osr3)
# Check giving (loc, scale) params for normal distribution
_osm, _osr = stats.probplot(x, sparams=(), fit=False)
osm, osr = stats.probplot(x, sparams=(), fit=False)
def test_dist_keyword(self):
np.random.seed(12345)
@ -437,9 +541,7 @@ class TestProbplot(TestCase):
assert_raises(AttributeError, stats.probplot, x, dist=[])
class custom_dist(object):
"""Some class that looks just enough like a distribution."""
def ppf(self, q):
return stats.norm.ppf(q, loc=2)
@ -482,8 +584,8 @@ class TestProbplot(TestCase):
def test_wilcoxon_bad_arg():
# Raise ValueError when two args of different lengths are given or
# zero_method is unknown.
assert_raises(ValueError, stats.wilcoxon, [1], [1, 2])
assert_raises(ValueError, stats.wilcoxon, [1, 2], [1, 2], "dummy")
assert_raises(ValueError, stats.wilcoxon, [1], [1,2])
assert_raises(ValueError, stats.wilcoxon, [1,2], [1,2], "dummy")
def test_mvsdist_bad_arg():
@ -519,7 +621,7 @@ class TestBoxcox_llf(TestCase):
x = stats.norm.rvs(size=10000, loc=10)
lmbda = 1
llf = stats.boxcox_llf(lmbda, x)
llf_expected = -x.size / 2. * np.log(np.sum(x.std() ** 2))
llf_expected = -x.size / 2. * np.log(np.sum(x.std()**2))
assert_allclose(llf, llf_expected)
def test_array_like(self):
@ -553,7 +655,7 @@ class TestBoxcox(TestCase):
xt = stats.boxcox(x, lmbda=1)
assert_allclose(xt, x - 1)
xt = stats.boxcox(x, lmbda=-1)
assert_allclose(xt, 1 - 1 / x)
assert_allclose(xt, 1 - 1/x)
xt = stats.boxcox(x, lmbda=0)
assert_allclose(xt, np.log(x))
@ -569,8 +671,8 @@ class TestBoxcox(TestCase):
np.random.seed(1245)
lmbda = 2.5
x = stats.norm.rvs(loc=10, size=50000)
x_inv = (x * lmbda + 1) ** (-lmbda)
_xt, maxlog = stats.boxcox(x_inv)
x_inv = (x * lmbda + 1)**(-lmbda)
xt, maxlog = stats.boxcox(x_inv)
assert_almost_equal(maxlog, -1 / lmbda, decimal=2)
@ -601,18 +703,17 @@ class TestBoxcox(TestCase):
class TestBoxcoxNormmax(TestCase):
def setUp(self):
np.random.seed(12345)
self.x = stats.loggamma.rvs(5, size=50) + 5
def test_pearsonr(self):
maxlog = stats.boxcox_normmax(self.x)
assert_allclose(maxlog, 1.804465325046)
assert_allclose(maxlog, 1.804465, rtol=1e-6)
def test_mle(self):
maxlog = stats.boxcox_normmax(self.x, method='mle')
assert_allclose(maxlog, 1.758101454114)
assert_allclose(maxlog, 1.758101, rtol=1e-6)
# Check that boxcox() uses 'mle'
_, maxlog_boxcox = stats.boxcox(self.x)
@ -620,11 +721,10 @@ class TestBoxcoxNormmax(TestCase):
def test_all(self):
maxlog_all = stats.boxcox_normmax(self.x, method='all')
assert_allclose(maxlog_all, [1.804465325046, 1.758101454114])
assert_allclose(maxlog_all, [1.804465, 1.758101], rtol=1e-6)
class TestBoxcoxNormplot(TestCase):
def setUp(self):
np.random.seed(7654321)
self.x = stats.loggamma.rvs(5, size=500) + 5
@ -662,9 +762,8 @@ class TestBoxcoxNormplot(TestCase):
class TestCircFuncs(TestCase):
def test_circfuncs(self):
x = np.array([355, 5, 2, 359, 10, 350])
x = np.array([355,5,2,359,10,350])
M = stats.circmean(x, high=360)
Mval = 0.167690146
assert_allclose(M, Mval, rtol=1e-7)
@ -678,7 +777,7 @@ class TestCircFuncs(TestCase):
assert_allclose(S, Sval, rtol=1e-7)
def test_circfuncs_small(self):
x = np.array([20, 21, 22, 18, 19, 20.5, 19.2])
x = np.array([20,21,22,18,19,20.5,19.2])
M1 = x.mean()
M2 = stats.circmean(x, high=360)
assert_allclose(M2, M1, rtol=1e-5)
@ -692,9 +791,9 @@ class TestCircFuncs(TestCase):
assert_allclose(S2, S1, rtol=1e-4)
def test_circmean_axis(self):
x = np.array([[355, 5, 2, 359, 10, 350],
[351, 7, 4, 352, 9, 349],
[357, 9, 8, 358, 4, 356]])
x = np.array([[355,5,2,359,10,350],
[351,7,4,352,9,349],
[357,9,8,358,4,356]])
M1 = stats.circmean(x, high=360)
M2 = stats.circmean(x.ravel(), high=360)
assert_allclose(M1, M2, rtol=1e-14)
@ -704,13 +803,13 @@ class TestCircFuncs(TestCase):
assert_allclose(M1, M2, rtol=1e-14)
M1 = stats.circmean(x, high=360, axis=0)
M2 = [stats.circmean(x[:, i], high=360) for i in range(x.shape[1])]
M2 = [stats.circmean(x[:,i], high=360) for i in range(x.shape[1])]
assert_allclose(M1, M2, rtol=1e-14)
def test_circvar_axis(self):
x = np.array([[355, 5, 2, 359, 10, 350],
[351, 7, 4, 352, 9, 349],
[357, 9, 8, 358, 4, 356]])
x = np.array([[355,5,2,359,10,350],
[351,7,4,352,9,349],
[357,9,8,358,4,356]])
V1 = stats.circvar(x, high=360)
V2 = stats.circvar(x.ravel(), high=360)
@ -721,13 +820,13 @@ class TestCircFuncs(TestCase):
assert_allclose(V1, V2, rtol=1e-11)
V1 = stats.circvar(x, high=360, axis=0)
V2 = [stats.circvar(x[:, i], high=360) for i in range(x.shape[1])]
V2 = [stats.circvar(x[:,i], high=360) for i in range(x.shape[1])]
assert_allclose(V1, V2, rtol=1e-11)
def test_circstd_axis(self):
x = np.array([[355, 5, 2, 359, 10, 350],
[351, 7, 4, 352, 9, 349],
[357, 9, 8, 358, 4, 356]])
x = np.array([[355,5,2,359,10,350],
[351,7,4,352,9,349],
[357,9,8,358,4,356]])
S1 = stats.circstd(x, high=360)
S2 = stats.circstd(x.ravel(), high=360)
@ -738,11 +837,11 @@ class TestCircFuncs(TestCase):
assert_allclose(S1, S2, rtol=1e-11)
S1 = stats.circstd(x, high=360, axis=0)
S2 = [stats.circstd(x[:, i], high=360) for i in range(x.shape[1])]
S2 = [stats.circstd(x[:,i], high=360) for i in range(x.shape[1])]
assert_allclose(S1, S2, rtol=1e-11)
def test_circfuncs_array_like(self):
x = [355, 5, 2, 359, 10, 350]
x = [355,5,2,359,10,350]
assert_allclose(stats.circmean(x, high=360), 0.167690146, rtol=1e-7)
assert_allclose(stats.circvar(x, high=360), 42.51955609, rtol=1e-7)
assert_allclose(stats.circstd(x, high=360), 6.520702116, rtol=1e-7)
@ -803,5 +902,108 @@ def test_wilcoxon_tie():
assert_allclose(p, expected_p, rtol=1e-6)
class TestMedianTest(TestCase):
def test_bad_n_samples(self):
# median_test requires at least two samples.
assert_raises(ValueError, stats.median_test, [1, 2, 3])
def test_empty_sample(self):
# Each sample must contain at least one value.
assert_raises(ValueError, stats.median_test, [], [1, 2, 3])
def test_empty_when_ties_ignored(self):
# The grand median is 1, and all values in the first argument are
# equal to the grand median. With ties="ignore", those values are
# ignored, which results in the first sample being (in effect) empty.
# This should raise a ValueError.
assert_raises(ValueError, stats.median_test,
[1, 1, 1, 1], [2, 0, 1], [2, 0], ties="ignore")
def test_empty_contingency_row(self):
# The grand median is 1, and with the default ties="below", all the
# values in the samples are counted as being below the grand median.
# This would result a row of zeros in the contingency table, which is
# an error.
assert_raises(ValueError, stats.median_test, [1, 1, 1], [1, 1, 1])
# With ties="above", all the values are counted as above the
# grand median.
assert_raises(ValueError, stats.median_test, [1, 1, 1], [1, 1, 1],
ties="above")
def test_bad_ties(self):
assert_raises(ValueError, stats.median_test, [1, 2, 3], [4, 5], ties="foo")
def test_bad_keyword(self):
assert_raises(TypeError, stats.median_test, [1, 2, 3], [4, 5], foo="foo")
def test_simple(self):
x = [1, 2, 3]
y = [1, 2, 3]
stat, p, med, tbl = stats.median_test(x, y)
# The median is floating point, but this equality test should be safe.
assert_equal(med, 2.0)
assert_array_equal(tbl, [[1, 1], [2, 2]])
# The expected values of the contingency table equal the contingency table,
# so the statistic should be 0 and the p-value should be 1.
assert_equal(stat, 0)
assert_equal(p, 1)
def test_ties_options(self):
# Test the contingency table calculation.
x = [1, 2, 3, 4]
y = [5, 6]
z = [7, 8, 9]
# grand median is 5.
# Default 'ties' option is "below".
stat, p, m, tbl = stats.median_test(x, y, z)
assert_equal(m, 5)
assert_equal(tbl, [[0, 1, 3], [4, 1, 0]])
stat, p, m, tbl = stats.median_test(x, y, z, ties="ignore")
assert_equal(m, 5)
assert_equal(tbl, [[0, 1, 3], [4, 0, 0]])
stat, p, m, tbl = stats.median_test(x, y, z, ties="above")
assert_equal(m, 5)
assert_equal(tbl, [[0, 2, 3], [4, 0, 0]])
def test_basic(self):
# median_test calls chi2_contingency to compute the test statistic
# and p-value. Make sure it hasn't screwed up the call...
x = [1, 2, 3, 4, 5]
y = [2, 4, 6, 8]
stat, p, m, tbl = stats.median_test(x, y)
assert_equal(m, 4)
assert_equal(tbl, [[1, 2], [4, 2]])
exp_stat, exp_p, dof, e = stats.chi2_contingency(tbl)
assert_allclose(stat, exp_stat)
assert_allclose(p, exp_p)
stat, p, m, tbl = stats.median_test(x, y, lambda_=0)
assert_equal(m, 4)
assert_equal(tbl, [[1, 2], [4, 2]])
exp_stat, exp_p, dof, e = stats.chi2_contingency(tbl, lambda_=0)
assert_allclose(stat, exp_stat)
assert_allclose(p, exp_p)
stat, p, m, tbl = stats.median_test(x, y, correction=False)
assert_equal(m, 4)
assert_equal(tbl, [[1, 2], [4, 2]])
exp_stat, exp_p, dof, e = stats.chi2_contingency(tbl, correction=False)
assert_allclose(stat, exp_stat)
assert_allclose(p, exp_p)
if __name__ == "__main__":
run_module_suite()

File diff suppressed because it is too large Load Diff

@ -4,22 +4,34 @@ Test functions for multivariate normal distributions.
"""
from __future__ import division, print_function, absolute_import
from numpy.testing import (assert_almost_equal,
run_module_suite, assert_allclose, assert_equal, assert_raises)
from numpy.testing import (
assert_allclose,
assert_almost_equal,
assert_array_almost_equal,
assert_equal,
assert_raises,
run_module_suite,
)
import numpy
import numpy as np
import scipy.linalg
#import wafo.stats._multivariate
from wafo.stats._multivariate import _PSD, _lnB
from wafo.stats import multivariate_normal
from wafo.stats import dirichlet, beta
from wafo.stats import norm
from wafo.stats._multivariate import _psd_pinv_decomposed_log_pdet
from scipy.integrate import romb
def test_input_shape():
mu = np.arange(3)
cov = np.identity(2)
assert_raises(ValueError, multivariate_normal.pdf, (0, 1), mu, cov)
assert_raises(ValueError, multivariate_normal.pdf, (0, 1, 2), mu, cov)
def test_scalar_values():
np.random.seed(1234)
@ -47,6 +59,63 @@ def test_logpdf():
assert_allclose(d1, np.log(d2))
def test_rank():
# Check that the rank is detected correctly.
np.random.seed(1234)
n = 4
mean = np.random.randn(n)
for expected_rank in range(1, n + 1):
s = np.random.randn(n, expected_rank)
cov = np.dot(s, s.T)
distn = multivariate_normal(mean, cov, allow_singular=True)
assert_equal(distn.cov_info.rank, expected_rank)
def _sample_orthonormal_matrix(n):
M = np.random.randn(n, n)
u, s, v = scipy.linalg.svd(M)
return u
def test_degenerate_distributions():
for n in range(1, 5):
x = np.random.randn(n)
for k in range(1, n + 1):
# Sample a small covariance matrix.
s = np.random.randn(k, k)
cov_kk = np.dot(s, s.T)
# Embed the small covariance matrix into a larger low rank matrix.
cov_nn = np.zeros((n, n))
cov_nn[:k, :k] = cov_kk
# Define a rotation of the larger low rank matrix.
u = _sample_orthonormal_matrix(n)
cov_rr = np.dot(u, np.dot(cov_nn, u.T))
y = np.dot(u, x)
# Check some identities.
distn_kk = multivariate_normal(np.zeros(k), cov_kk,
allow_singular=True)
distn_nn = multivariate_normal(np.zeros(n), cov_nn,
allow_singular=True)
distn_rr = multivariate_normal(np.zeros(n), cov_rr,
allow_singular=True)
assert_equal(distn_kk.cov_info.rank, k)
assert_equal(distn_nn.cov_info.rank, k)
assert_equal(distn_rr.cov_info.rank, k)
pdf_kk = distn_kk.pdf(x[:k])
pdf_nn = distn_nn.pdf(x)
pdf_rr = distn_rr.pdf(y)
assert_allclose(pdf_kk, pdf_nn)
assert_allclose(pdf_kk, pdf_rr)
logpdf_kk = distn_kk.logpdf(x[:k])
logpdf_nn = distn_nn.logpdf(x)
logpdf_rr = distn_rr.logpdf(y)
assert_allclose(logpdf_kk, logpdf_nn)
assert_allclose(logpdf_kk, logpdf_rr)
def test_large_pseudo_determinant():
# Check that large pseudo-determinants are handled appropriately.
@ -67,11 +136,12 @@ def test_large_pseudo_determinant():
# np.linalg.slogdet is only available in numpy 1.6+
# but scipy currently supports numpy 1.5.1.
#assert_allclose(np.linalg.slogdet(cov[:npos, :npos]), (1, large_total_log))
# assert_allclose(np.linalg.slogdet(cov[:npos, :npos]),
# (1, large_total_log))
# Check the pseudo-determinant.
U, log_pdet = _psd_pinv_decomposed_log_pdet(cov)
assert_allclose(log_pdet, large_total_log)
psd = _PSD(cov)
assert_allclose(psd.log_pdet, large_total_log)
def test_broadcasting():
@ -111,7 +181,7 @@ def test_marginalization():
# yield a 1D Gaussian
mean = np.array([2.5, 3.5])
cov = np.array([[.5, 0.2], [0.2, .6]])
n = 2**8 + 1 # Number of samples
n = 2 ** 8 + 1 # Number of samples
delta = 6 / (n - 1) # Grid spacing
v = np.linspace(0, 6, n)
@ -126,8 +196,8 @@ def test_marginalization():
margin_y = romb(pdf, delta, axis=1)
# Compare with standard normal distribution
gauss_x = norm.pdf(v, loc=mean[0], scale=cov[0, 0]**0.5)
gauss_y = norm.pdf(v, loc=mean[1], scale=cov[1, 1]**0.5)
gauss_x = norm.pdf(v, loc=mean[0], scale=cov[0, 0] ** 0.5)
gauss_y = norm.pdf(v, loc=mean[1], scale=cov[1, 1] ** 0.5)
assert_allclose(margin_x, gauss_x, rtol=1e-2, atol=1e-2)
assert_allclose(margin_y, gauss_y, rtol=1e-2, atol=1e-2)
@ -160,33 +230,43 @@ def test_pseudodet_pinv():
# Set cond so that the lowest eigenvalue is below the cutoff
cond = 1e-5
U, log_pdet = _psd_pinv_decomposed_log_pdet(cov, cond)
pinv = np.dot(U, U.T)
_, log_pdet_pinv = _psd_pinv_decomposed_log_pdet(pinv, cond)
psd = _PSD(cov, cond=cond)
psd_pinv = _PSD(psd.pinv, cond=cond)
# Check that the log pseudo-determinant agrees with the sum
# of the logs of all but the smallest eigenvalue
assert_allclose(log_pdet, np.sum(np.log(s[:-1])))
assert_allclose(psd.log_pdet, np.sum(np.log(s[:-1])))
# Check that the pseudo-determinant of the pseudo-inverse
# agrees with 1 / pseudo-determinant
assert_allclose(-log_pdet, log_pdet_pinv)
assert_allclose(-psd.log_pdet, psd_pinv.log_pdet)
def test_exception_nonsquare_cov():
cov = [[1, 2, 3], [4, 5, 6]]
assert_raises(ValueError, _psd_pinv_decomposed_log_pdet, cov)
assert_raises(ValueError, _PSD, cov)
def test_exception_nonfinite_cov():
cov_nan = [[1, 0], [0, np.nan]]
assert_raises(ValueError, _psd_pinv_decomposed_log_pdet, cov_nan)
assert_raises(ValueError, _PSD, cov_nan)
cov_inf = [[1, 0], [0, np.inf]]
assert_raises(ValueError, _psd_pinv_decomposed_log_pdet, cov_inf)
assert_raises(ValueError, _PSD, cov_inf)
def test_exception_non_psd_cov():
cov = [[1, 0], [0, -1]]
assert_raises(ValueError, _psd_pinv_decomposed_log_pdet, cov)
assert_raises(ValueError, _PSD, cov)
def test_exception_singular_cov():
np.random.seed(1234)
x = np.random.randn(5)
mean = np.random.randn(5)
cov = np.ones((5, 5))
e = np.linalg.LinAlgError
assert_raises(e, multivariate_normal, mean, cov)
assert_raises(e, multivariate_normal.pdf, x, mean, cov)
assert_raises(e, multivariate_normal.logpdf, x, mean, cov)
def test_R_values():
@ -216,6 +296,14 @@ def test_R_values():
assert_allclose(pdf, r_pdf, atol=1e-10)
def test_multivariate_normal_rvs_zero_covariance():
mean = np.zeros(2)
covariance = np.zeros((2, 2))
model = multivariate_normal(mean, covariance, allow_singular=True)
sample = model.rvs()
assert_equal(sample, [0, 0])
def test_rvs_shape():
# Check that rvs parses the mean and covariance correctly, and returns
# an array of the right shape
@ -267,9 +355,131 @@ def test_entropy():
# Compare entropy with manually computed expression involving
# the sum of the logs of the eigenvalues of the covariance matrix
eigs = np.linalg.eig(cov)[0]
desired = 1/2 * (n * (np.log(2*np.pi) + 1) + np.sum(np.log(eigs)))
desired = 1 / 2 * (n * (np.log(2 * np.pi) + 1) + np.sum(np.log(eigs)))
assert_almost_equal(desired, rv.entropy())
def test_lnB():
alpha = np.array([1, 1, 1])
desired = .5 # e^lnB = 1/2 for [1, 1, 1]
assert_almost_equal(np.exp(_lnB(alpha)), desired)
def test_frozen_dirichlet():
np.random.seed(2846)
n = np.random.randint(1, 32)
alpha = np.random.uniform(10e-10, 100, n)
d = dirichlet(alpha)
assert_equal(d.var(), dirichlet.var(alpha))
assert_equal(d.mean(), dirichlet.mean(alpha))
assert_equal(d.entropy(), dirichlet.entropy(alpha))
num_tests = 10
for i in range(num_tests):
x = np.random.uniform(10e-10, 100, n)
x /= np.sum(x)
assert_equal(d.pdf(x[:-1]), dirichlet.pdf(x[:-1], alpha))
assert_equal(d.logpdf(x[:-1]), dirichlet.logpdf(x[:-1], alpha))
def test_simple_values():
alpha = np.array([1, 1])
d = dirichlet(alpha)
assert_almost_equal(d.mean(), 0.5)
assert_almost_equal(d.var(), 1. / 12.)
b = beta(1, 1)
assert_almost_equal(d.mean(), b.mean())
assert_almost_equal(d.var(), b.var())
def test_K_and_K_minus_1_calls_equal():
# Test that calls with K and K-1 entries yield the same results.
np.random.seed(2846)
n = np.random.randint(1, 32)
alpha = np.random.uniform(10e-10, 100, n)
d = dirichlet(alpha)
num_tests = 10
for i in range(num_tests):
x = np.random.uniform(10e-10, 100, n)
x /= np.sum(x)
assert_almost_equal(d.pdf(x[:-1]), d.pdf(x))
def test_multiple_entry_calls():
# Test that calls with multiple x vectors as matrix work
np.random.seed(2846)
n = np.random.randint(1, 32)
alpha = np.random.uniform(10e-10, 100, n)
d = dirichlet(alpha)
num_tests = 10
num_multiple = 5
xm = None
for i in range(num_tests):
for m in range(num_multiple):
x = np.random.uniform(10e-10, 100, n)
x /= np.sum(x)
if xm is not None:
xm = np.vstack((xm, x))
else:
xm = x
rm = d.pdf(xm.T)
rs = None
for xs in xm:
r = d.pdf(xs)
if rs is not None:
rs = np.append(rs, r)
else:
rs = r
assert_array_almost_equal(rm, rs)
def test_2D_dirichlet_is_beta():
np.random.seed(2846)
alpha = np.random.uniform(10e-10, 100, 2)
d = dirichlet(alpha)
b = beta(alpha[0], alpha[1])
num_tests = 10
for i in range(num_tests):
x = np.random.uniform(10e-10, 100, 2)
x /= np.sum(x)
assert_almost_equal(b.pdf(x), d.pdf([x]))
assert_almost_equal(b.mean(), d.mean()[0])
assert_almost_equal(b.var(), d.var()[0])
def test_dimensions_mismatch():
# Regression test for GH #3493. Check that setting up a PDF with a mean of
# length M and a covariance matrix of size (N, N), where M != N, raises a
# ValueError with an informative error message.
mu = np.array([0.0, 0.0])
sigma = np.array([[1.0]])
assert_raises(ValueError, multivariate_normal, mu, sigma)
# A simple check that the right error message was passed along. Checking
# that the entire message is there, word for word, would be somewhat
# fragile, so we just check for the leading part.
try:
multivariate_normal(mu, sigma)
except ValueError as e:
msg = "Dimension mismatch"
assert_equal(str(e)[:len(msg)], msg)
if __name__ == "__main__":
run_module_suite()

@ -8,13 +8,15 @@
"""
from __future__ import division, print_function, absolute_import
import sys
import warnings
from collections import namedtuple
from numpy.testing import TestCase, assert_, assert_equal, \
assert_almost_equal, assert_array_almost_equal, assert_array_equal, \
assert_approx_equal, assert_raises, run_module_suite, \
assert_allclose, dec
from numpy.testing import (TestCase, assert_, assert_equal,
assert_almost_equal, assert_array_almost_equal,
assert_array_equal, assert_approx_equal,
assert_raises, run_module_suite, assert_allclose,
dec)
import numpy.ma.testutils as mat
from numpy import array, arange, float32, float64, power
import numpy as np
@ -170,6 +172,14 @@ class TestNanFunc(TestCase):
m = stats.nanmedian(self.X)
assert_approx_equal(m, np.median(self.X))
def test_nanmedian_axis(self):
# Check nanmedian with axis
X = self.X.reshape(3,3)
m = stats.nanmedian(X, axis=0)
assert_equal(m, np.median(X, axis=0))
m = stats.nanmedian(X, axis=1)
assert_equal(m, np.median(X, axis=1))
def test_nanmedian_some(self):
# Check nanmedian when some values only are nan.
m = stats.nanmedian(self.Xsome)
@ -177,8 +187,21 @@ class TestNanFunc(TestCase):
def test_nanmedian_all(self):
# Check nanmedian when all values are nan.
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
m = stats.nanmedian(self.Xall)
assert_(np.isnan(m))
assert_equal(len(w), 1)
assert_(issubclass(w[0].category, RuntimeWarning))
def test_nanmedian_all_axis(self):
# Check nanmedian when all values are nan.
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
m = stats.nanmedian(self.Xall.reshape(3,3), axis=1)
assert_(np.isnan(m).all())
assert_equal(len(w), 3)
assert_(issubclass(w[0].category, RuntimeWarning))
def test_nanmedian_scalars(self):
# Check nanmedian for scalar inputs. See ticket #1098.
@ -449,6 +472,11 @@ class TestFisherExact(TestCase):
res.append(stats.fisher_exact(table, alternative="greater")[1])
assert_allclose(res, pval, atol=0, rtol=1e-7)
def test_gh3014(self):
# check if issue #3014 has been fixed.
# before, this would have risen a ValueError
odds, pvalue = stats.fisher_exact([[1, 2], [9, 84419233]])
class TestCorrSpearmanr(TestCase):
""" W.II.D. Compute a correlation matrix on all the variables.
@ -601,9 +629,12 @@ def test_kendalltau():
assert_approx_equal(res[1], expected[1])
# with only ties in one or both inputs
assert_(np.all(np.isnan(stats.kendalltau([2,2,2], [2,2,2]))))
assert_(np.all(np.isnan(stats.kendalltau([2,0,2], [2,2,2]))))
assert_(np.all(np.isnan(stats.kendalltau([2,2,2], [2,0,2]))))
assert_equal(stats.kendalltau([2,2,2], [2,2,2]), (np.nan, np.nan))
assert_equal(stats.kendalltau([2,0,2], [2,2,2]), (np.nan, np.nan))
assert_equal(stats.kendalltau([2,2,2], [2,0,2]), (np.nan, np.nan))
# empty arrays provided as input
assert_equal(stats.kendalltau([], []), (np.nan, np.nan))
# check two different sort methods
assert_approx_equal(stats.kendalltau(x1, x2, initial_lexsort=False)[1],
@ -718,6 +749,21 @@ class TestRegression(TestCase):
assert_(not np.isnan(res[4])) # stderr should stay finite
def test_theilslopes():
# Basic slope test.
slope, intercept, lower, upper = stats.theilslopes([0,1,1])
assert_almost_equal(slope, 0.5)
assert_almost_equal(intercept, 0.5)
# Test of confidence intervals.
x = [1, 2, 3, 4, 10, 12, 18]
y = [9, 15, 19, 20, 45, 55, 78]
slope, intercept, lower, upper = stats.theilslopes(y, x, 0.07)
assert_almost_equal(slope, 4)
assert_almost_equal(upper, 4.38, decimal=2)
assert_almost_equal(lower, 3.71, decimal=2)
class TestHistogram(TestCase):
# Tests that histogram works as it should, and keeps old behaviour
#
@ -1032,9 +1078,23 @@ class TestScoreatpercentile(TestCase):
assert_equal(scoreatperc(np.array([1, 10, 100]), 50, limit=(1, 10),
interpolation_method='higher'), 10)
def test_sequence(self):
def test_sequence_per(self):
x = arange(8) * 0.5
assert_equal(stats.scoreatpercentile(x, [0, 100, 50]), [0, 3.5, 1.75])
expected = np.array([0, 3.5, 1.75])
res = stats.scoreatpercentile(x, [0, 100, 50])
assert_allclose(res, expected)
assert_(isinstance(res, np.ndarray))
# Test with ndarray. Regression test for gh-2861
assert_allclose(stats.scoreatpercentile(x, np.array([0, 100, 50])),
expected)
# Also test combination of 2-D array, axis not None and array-like per
res2 = stats.scoreatpercentile(np.arange(12).reshape((3,4)),
np.array([0, 1, 100, 100]), axis=1)
expected2 = array([[0, 4, 8],
[0.03, 4.03, 8.03],
[3, 7, 11],
[3, 7, 11]])
assert_allclose(res2, expected2)
def test_axis(self):
scoreatperc = stats.scoreatpercentile
@ -1054,6 +1114,11 @@ class TestScoreatpercentile(TestCase):
assert_raises(ValueError, stats.scoreatpercentile, [1], 101)
assert_raises(ValueError, stats.scoreatpercentile, [1], -1)
def test_empty(self):
assert_equal(stats.scoreatpercentile([], 50), np.nan)
assert_equal(stats.scoreatpercentile(np.array([[], []]), 50), np.nan)
assert_equal(stats.scoreatpercentile([], [50, 99]), [np.nan, np.nan])
class TestItemfreq(object):
a = [5, 7, 1, 2, 1, 5, 7] * 10
@ -1089,7 +1154,7 @@ class TestItemfreq(object):
bb = np.array(list(zip(b, b)), dt)
v = stats.itemfreq(aa)
# Arrays don't compare equal because v[:,0] is object array
assert_equal(v[2, 0], bb[2])
assert_equal(tuple(v[2, 0]), tuple(bb[2]))
class TestMode(TestCase):
@ -1099,6 +1164,71 @@ class TestMode(TestCase):
assert_almost_equal(vals[0][0],6)
assert_almost_equal(vals[1][0],3)
def test_axes(self):
data1 = [10,10,30,40]
data2 = [10,10,10,10]
data3 = [20,10,20,20]
data4 = [30,30,30,30]
data5 = [40,30,30,30]
arr = np.array([data1, data2, data3, data4, data5])
vals = stats.mode(arr, axis=None)
assert_almost_equal(vals[0],np.array([30]))
assert_almost_equal(vals[1],np.array([8]))
vals = stats.mode(arr, axis=0)
assert_almost_equal(vals[0],np.array([[10,10,30,30]]))
assert_almost_equal(vals[1],np.array([[2,3,3,2]]))
vals = stats.mode(arr, axis=1)
assert_almost_equal(vals[0],np.array([[10],[10],[20],[30],[30]]))
assert_almost_equal(vals[1],np.array([[2],[4],[3],[4],[3]]))
def test_strings(self):
data1 = ['rain', 'showers', 'showers']
vals = stats.mode(data1)
expected = ['showers']
assert_equal(vals[0][0], 'showers')
assert_equal(vals[1][0], 2)
@dec.knownfailureif(sys.version_info > (3,), 'numpy github issue 641')
def test_mixed_objects(self):
objects = [10, True, np.nan, 'hello', 10]
arr = np.empty((5,), dtype=object)
arr[:] = objects
vals = stats.mode(arr)
assert_equal(vals[0][0], 10)
assert_equal(vals[1][0], 2)
def test_objects(self):
"""Python objects must be sortable (le + eq) and have ne defined
for np.unique to work. hash is for set.
"""
class Point(object):
def __init__(self, x):
self.x = x
def __eq__(self, other):
return self.x == other.x
def __ne__(self, other):
return self.x != other.x
def __lt__(self, other):
return self.x < other.x
def __hash__(self):
return hash(self.x)
points = [Point(x) for x in [1,2,3,4,3,2,2,2]]
arr = np.empty((8,), dtype=object)
arr[:] = points
assert len(set(points)) == 4
assert_equal(np.unique(arr).shape, (4,))
vals = stats.mode(arr)
assert_equal(vals[0][0], Point(2))
assert_equal(vals[1][0], 4)
class TestVariability(TestCase):
@ -1120,7 +1250,7 @@ class TestVariability(TestCase):
# y = stats.sem(self.shoes[0])
# assert_approx_equal(y,0.775177399)
y = stats.sem(self.testcase)
assert_approx_equal(y,0.6454972244)
assert_approx_equal(y, 0.6454972244)
n = len(self.testcase)
assert_allclose(stats.sem(self.testcase, ddof=0) * np.sqrt(n/(n-2)),
stats.sem(self.testcase, ddof=2))
@ -1660,6 +1790,7 @@ def test_chisquare_masked_arrays():
# Empty arrays:
# A data set with length 0 returns a masked scalar.
with np.errstate(invalid='ignore'):
chisq, p = stats.chisquare(np.ma.array([]))
assert_(isinstance(chisq, np.ma.MaskedArray))
assert_equal(chisq.shape, ())
@ -1675,6 +1806,7 @@ def test_chisquare_masked_arrays():
# empty3.T is an array containing 3 data sets, each with length 0,
# so an array of size (3,) is returned, with all values masked.
with np.errstate(invalid='ignore'):
chisq, p = stats.chisquare(empty3.T)
assert_(isinstance(chisq, np.ma.MaskedArray))
assert_equal(chisq.shape, (3,))
@ -2622,22 +2754,25 @@ class TestSigamClip(object):
class TestFOneWay(TestCase):
def test_trivial(self):
# A trivial test of stats.f_oneway, with F=0.
F, p = stats.f_oneway([0,2], [0,2])
assert_equal(F, 0.0)
def test_basic(self):
# A test of stats.f_oneway, with F=2.
F, p = stats.f_oneway([0,2], [2,4])
# Despite being a floating point calculation, this data should
# result in F being exactly 2.0.
F, p = stats.f_oneway([0,2], [2,4])
assert_equal(F, 2.0)
def test_large_integer_array(self):
a = np.array([655, 788], dtype=np.uint16)
b = np.array([789, 772], dtype=np.uint16)
F, p = stats.f_oneway(a, b)
assert_almost_equal(F, 0.77450216931805538)
class TestKruskal(TestCase):
class TestKruskal(TestCase):
def test_simple(self):
x = [1]
y = [2]

@ -18,7 +18,7 @@ def test_tukeylambda_stats_known_exact():
# lambda = 0
var = tukeylambda_variance(0)
assert_allclose(var, np.pi ** 2 / 3, atol=1e-12)
assert_allclose(var, np.pi**2 / 3, atol=1e-12)
kurt = tukeylambda_kurtosis(0)
assert_allclose(kurt, 1.2, atol=1e-10)
@ -26,7 +26,7 @@ def test_tukeylambda_stats_known_exact():
var = tukeylambda_variance(0.5)
assert_allclose(var, 4 - np.pi, atol=1e-12)
kurt = tukeylambda_kurtosis(0.5)
desired = (5. / 3 - np.pi / 2) / (np.pi / 4 - 1) ** 2 - 3
desired = (5./3 - np.pi/2) / (np.pi/4 - 1)**2 - 3
assert_allclose(kurt, desired, atol=1e-10)
# lambda = 1

@ -297,9 +297,11 @@ def test_hygfz():
assert_almost_equal(1.0464328112173522, hygfz(0.1, 0.2, 0.3, 0.5))
assert_almost_equal(1.2027034401166194, hygfz(0.1, 0.2, 0.3, 0.95))
#assert_equal(1.661006238211309e-07, hygfz(5, -300, 10, 0.5))
assert_equal(0.118311386286, hygfz(0.5, -99.0, 1.5, 0.5625))
assert_equal(0.0965606007742, hygfz(0.5, -149.0, 1.5, 0.5625))
assert_equal(0.49234384000963544+0.60513406166123973j, hygfz(1, 1, 4, 3+4j))
#assert_equal(0.118311386286, hygfz(0.5, -99.0, 1.5, 0.5625))
#assert_equal(0.0965606007742, hygfz(0.5, -149.0, 1.5, 0.5625))
#assert_equal(0.49234384000963544 + 0.60513406166123973j,
# hygfz(1, 1, 4, 3 + 4j))
def test_common_shape():
A = np.ones((4, 1))

@ -2,5 +2,6 @@
Transform package in WAFO Toolbox.
"""
from core import *
import models
from .core import *
from . import models
from . import estimation

@ -2,14 +2,16 @@
'''
from __future__ import division
#import numpy as np
from numpy import trapz, sqrt, linspace #@UnresolvedImport
from numpy import trapz, sqrt, linspace # @UnresolvedImport
from wafo.wafodata import PlotData
from wafo.misc import tranproc #, trangood
from wafo.containers import PlotData
from wafo.misc import tranproc # , trangood
__all__ = ['TrData', 'TrCommon']
class TrCommon(object):
"""
<generic> transformation model, g.
@ -37,7 +39,7 @@ class TrCommon(object):
"""
def __init__(self, mean=0.0, var=1.0, skew=0.16, kurt=3.04, *args, **kwds):
sigma = kwds.get('sigma',None)
sigma = kwds.get('sigma', None)
if sigma is None:
sigma = sqrt(var)
self.mean = mean
@ -74,12 +76,12 @@ class TrCommon(object):
"""
if x is None:
xn = linspace(xnmin, xnmax, n)
x = self.sigma*xn+self.mean
x = self.sigma * xn + self.mean
else:
xn = (x-self.mean)/self.sigma
xn = (x - self.mean) / self.sigma
yn = (self._dat2gauss(x)-self.ymean)/self.ysigma
t0 = trapz((xn-yn)**2., xn)
yn = (self._dat2gauss(x) - self.ymean) / self.ysigma
t0 = trapz((xn - yn) ** 2., xn)
return t0
def gauss2dat(self, y, *yi):
@ -102,8 +104,10 @@ class TrCommon(object):
tranproc
"""
return self._gauss2dat(y, *yi)
def _gauss2dat(self, y, *yi):
pass
def dat2gauss(self, x, *xi):
"""
Transforms non-linear data, x, to Gaussian scale.
@ -111,8 +115,8 @@ class TrCommon(object):
Parameters
----------
x, x1,...,xn : array-like
input vectors with non-linear data values, where xi is the i'th time
derivative of x. (n<=4)
input vectors with non-linear data values, where xi is the i'th
time derivative of x. (n<=4)
Returns
-------
y, y1,...,yn : array-like
@ -124,18 +128,21 @@ class TrCommon(object):
tranproc.
"""
return self._dat2gauss(x, *xi)
def _dat2gauss(self, x, *xi):
pass
class TrData(PlotData, TrCommon):
__doc__ = TrCommon.__doc__.split('mean')[0].replace('<generic>','Data' #@ReservedAssignment
) + """
__doc__ = TrCommon.__doc__.split('mean')[0].replace('<generic>',
'Data') + """
data : array-like
Gaussian values, Y
args : array-like
non-Gaussian values, X
ymean, ysigma : real, scalars (default ymean=0, ysigma=1)
mean and standard-deviation, respectively, of the process in Gaussian world.
mean and standard-deviation, respectively, of the process in Gaussian
world.
mean, sigma : real, scalars
mean and standard-deviation, respectively, of the non-Gaussian process.
Default:
@ -167,6 +174,7 @@ class TrData(PlotData, TrCommon):
>>> g.dist2gauss() < 1e-16
True
"""
def __init__(self, *args, **kwds):
options = dict(title='Transform',
xlab='x', ylab='g(x)',
@ -183,11 +191,12 @@ class TrData(PlotData, TrCommon):
#self.mean = np.mean(self.args) #
self.mean = self.gauss2dat(self.ymean)
if self.sigma is None:
yp = self.ymean+self.ysigma
ym = self.ymean-self.ysigma
self.sigma = (self.gauss2dat(yp)-self.gauss2dat(ym))/2.
yp = self.ymean + self.ysigma
ym = self.ymean - self.ysigma
self.sigma = (self.gauss2dat(yp) - self.gauss2dat(ym)) / 2.
self.children = [PlotData((self.args-self.mean)/self.sigma, self.args)]
self.children = [
PlotData((self.args - self.mean) / self.sigma, self.args)]
def trdata(self):
return self
@ -198,11 +207,14 @@ class TrData(PlotData, TrCommon):
def _dat2gauss(self, x, *xi):
return tranproc(self.args, self.data, x, *xi)
class EstimateTransform(object):
pass
def main():
pass
if __name__ == '__main__':
if True: #False : #
if True: # False : #
import doctest
doctest.testmod()
else:

@ -5,21 +5,11 @@ TrHermite
TrOchi
TrLinear
'''
#-------------------------------------------------------------------------------
# Name: transform.models
# Purpose:
#
# Author: pab
#
# Created: 24.11.2008
# Copyright: (c) pab 2008
# Licence: <your licence>
#-------------------------------------------------------------------------------
#!/usr/bin/env python
# !/usr/bin/env python
from __future__ import division
from scipy.optimize import brentq
from numpy import (sqrt, atleast_1d, abs, imag, sign, where, cos, arccos, ceil, #@UnresolvedImport
expm1, log1p, pi) #@UnresolvedImport
from numpy import (sqrt, atleast_1d, abs, imag, sign, where, cos, arccos, ceil, # @UnresolvedImport
expm1, log1p, pi) # @UnresolvedImport
import numpy as np
import warnings
from core import TrCommon, TrData
@ -42,9 +32,12 @@ _example = '''
>>> g2 = tm.<generic>(mean=me, var=va, skew=sk, kurt=ku, ysigma=std)
>>> xs = g2.gauss2dat(ys[:,1:]) # Transformed to the real world
'''
class TrCommon2(TrCommon):
__doc__ = TrCommon.__doc__ #@ReservedAssignment
def trdata(self, x=None, xnmin= -5, xnmax=5, n=513):
__doc__ = TrCommon.__doc__ # @ReservedAssignment
def trdata(self, x=None, xnmin=-5, xnmax=5, n=513):
"""
Return a discretized transformation model.
@ -74,8 +67,9 @@ class TrCommon2(TrCommon):
return TrData(yn, x, mean=self.mean, sigma=self.sigma)
class TrHermite(TrCommon2):
__doc__ = TrCommon2.__doc__.replace('<generic>', 'Hermite' #@ReservedAssignment
__doc__ = TrCommon2.__doc__.replace('<generic>', 'Hermite' # @ReservedAssignment
) + """
pardef : scalar, integer
1 Winterstein et. al. (1994) parametrization [1]_ (default)
@ -135,6 +129,7 @@ class TrHermite(TrCommon2):
'Nonlinear vibration models for extremes and fatigue.'
J. Engng. Mech., ASCE, Vol 114, No 10, pp 1772-1790
"""
def __init__(self, *args, **kwds):
super(TrHermite, self).__init__(*args, **kwds)
self.pardef = kwds.get('pardef', 1)
@ -167,11 +162,13 @@ class TrHermite(TrCommon2):
if (ga2 < 0) or (12 < ga2):
warnings.warn('Kurtosis must be between 0 and 12')
self._c3 = skew / 6 * (1 - 0.015 * abs(skew) + 0.3 * skew ** 2) / (1 + 0.2 * ga2)
self._c3 = skew / 6 * \
(1 - 0.015 * abs(skew) + 0.3 * skew ** 2) / (1 + 0.2 * ga2)
if ga2 == 0.:
self._c4 = 0.0
else:
c41 = (1. - 1.43 * skew ** 2. / ga2) ** (1. - 0.1 * (ga2 + 3.) ** 0.8)
expon = 1. - 0.1 * (ga2 + 3.) ** 0.8
c41 = (1. - 1.43 * skew ** 2. / ga2) ** (expon)
self._c4 = 0.1 * ((1. + 1.25 * ga2) ** (1. / 3.) - 1.) * c41
if not np.isfinite(self._c3) or not np.isfinite(self._c4):
@ -192,20 +189,21 @@ class TrHermite(TrCommon2):
if abs(c4) < sqrt(eps):
c4 = 0.0
#gdef = self.kurt-3.0
# gdef = self.kurt-3.0
if self.kurt < 3.0:
p = np.poly1d([-c4, -c3, 1. + 3. * c4, c3]) # forward, g
self._forward = p
self._backward = None
else:
Km1 = np.sqrt(1. + 2. * c3 ** 2 + 6 * c4 ** 2)
p = np.poly1d(np.r_[c4, c3, 1. - 3. * c4, -c3] / Km1) # backward G
# backward G
p = np.poly1d(np.r_[c4, c3, 1. - 3. * c4, -c3] / Km1)
self._forward = None
self._backward = p
#% Check if it is a strictly increasing function.
dp = p.deriv(m=1) #% Derivative
r = dp.r #% Find roots of the derivative
# Check if it is a strictly increasing function.
dp = p.deriv(m=1) # % Derivative
r = dp.r # % Find roots of the derivative
r = r[where(abs(imag(r)) < eps)] # Keep only real roots
if r.size > 0:
@ -219,6 +217,7 @@ class TrHermite(TrCommon2):
The derivative of g(x) is infinite at x = %g''' % self._x_limit
warnings.warn(txt1)
return
def check_forward(self, x):
if not (self._x_limit is None):
x00 = self._x_limit
@ -227,13 +226,13 @@ class TrHermite(TrCommon2):
if any(np.logical_and(x[0] <= x00, x00 <= x[-1])):
cdef = 1
else:
cdef = sum(np.logical_xor(x00 <= x[0] , x00 <= x[-1]))
cdef = sum(np.logical_xor(x00 <= x[0], x00 <= x[-1]))
if np.mod(cdef, 2):
errtxt = 'Unable to invert the polynomial \n %s' % txt2
raise ValueError(errtxt)
np.disp('However, successfully inverted the polynomial\n %s' % txt2)
np.disp(
'However, successfully inverted the polynomial\n %s' % txt2)
def _dat2gauss(self, x, *xi):
if len(xi) > 0:
@ -244,7 +243,7 @@ class TrHermite(TrCommon2):
xn = (xn - self.mean) / self.sigma
if self._forward is None:
#Inverting the polynomial
# Inverting the polynomial
yn = self._poly_inv(self._backward, xn)
else:
yn = self._forward(xn)
@ -254,11 +253,10 @@ class TrHermite(TrCommon2):
if len(yi) > 0:
raise ValueError('Transforming derivatives is not implemented!')
yn = (atleast_1d(y) - self.ymean) / self.ysigma
#self.check_forward(y)
# self.check_forward(y)
if self._backward is None:
#% Inverting the polynomial
#%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Inverting the polynomial
xn = self._poly_inv(self._forward, yn)
else:
xn = self._backward(yn)
@ -277,7 +275,7 @@ class TrHermite(TrCommon2):
b = coefs[1]
c = coefs[2] - xn
t = 0.5 * (b + sign(b) * sqrt(b ** 2 - 4 * a * c))
#so1 = t/a # largest solution
# so1 = t/a # largest solution
so2 = -c / t # smallest solution
return so2
elif p.order == 3:
@ -290,25 +288,24 @@ class TrHermite(TrCommon2):
c = coefs[2] - xn / p.coeffs[0]
x0 = a / 3.
#% substitue xn = z-x0 and divide by c4 => z^3 + 3*p1*z+2*q0 = 0
# substitue xn = z-x0 and divide by c4 => z^3 + 3*p1*z+2*q0 = 0
p1 = b / 3 - x0 ** 2
#p1 = (b-a**2/3)/3
# p1 = (b-a**2/3)/3
#q0 = (c + x0*(2.*x0/3.-b))/2.
#q0 = x0**3 -a*b/6 +c/2
# q0 = (c + x0*(2.*x0/3.-b))/2.
# q0 = x0**3 -a*b/6 +c/2
q0 = x0 * (x0 ** 2 - b / 2) + c / 2
## # z^3+3*p1*z+2*q0=0
## c3 = self._c3
## c4 = self._c4
## b1 = 1./(3.*c4)
## #x0 = c3*b1
## #% substitue u = z-x0 and divide by c4 => z^3 + 3*c*z+2*q0 = 0
## #p1 = b1-1.-x0**2.
## Km1 = np.sqrt(1.+2.*c3**2+6*c4**2)
## q0 = x0**3-1.5*b1*(x0+xn*Km1)
#q0 = x0**3-1.5*b1*(x0+xn)
# z^3+3*p1*z+2*q0=0
# c3 = self._c3
# c4 = self._c4
# b1 = 1./(3.*c4)
# x0 = c3*b1
# % substitue u = z-x0 and divide by c4 => z^3 + 3*c*z+2*q0 = 0
# p1 = b1-1.-x0**2.
# Km1 = np.sqrt(1.+2.*c3**2+6*c4**2)
# q0 = x0**3-1.5*b1*(x0+xn*Km1)
# q0 = x0**3-1.5*b1*(x0+xn)
if not (self._x_limit is None): # % Three real roots
d = sqrt(-p1)
theta1 = arccos(-q0 / d ** 3) / 3
@ -318,18 +315,17 @@ class TrHermite(TrCommon2):
return 2. * d * cos(theta1 + th2[ix]) - x0
else: # %Only one real root exist
q1 = sqrt((q0) ** 2 + p1 ** 3)
#% Find the real root of the monic polynomial
# Find the real root of the monic polynomial
A0 = (q1 - q0) ** (1. / 3.)
B0 = -(q1 + q0) ** (1. / 3.)
return A0 + B0 - x0 #% real root
return A0 + B0 - x0 # % real root
#%% The other complex roots are given by
#%x= -(A0+B0)/2+(A0-B0)*sqrt(3)/2-x0
#%x=-(A0+B0)/2+(A0-B0)*sqrt(-3)/2-x0
class TrLinear(TrCommon2):
__doc__ = TrCommon2.__doc__.replace('<generic>', 'Linear' #@ReservedAssignment
__doc__ = TrCommon2.__doc__.replace('<generic>', 'Linear' # @ReservedAssignment
) + """
Description
-----------
@ -355,11 +351,12 @@ class TrLinear(TrCommon2):
spec2skew, ochitr, lc2tr, dat2tr
"""
def _dat2gauss(self, x, *xi):
sratio = atleast_1d(self.ysigma / self.sigma)
y = (atleast_1d(x) - self.mean) * sratio + self.ymean
if len(xi) > 0:
y = [y, ] + [ ix * sratio for ix in xi]
y = [y, ] + [ix * sratio for ix in xi]
return y
def _gauss2dat(self, y, *yi):
@ -371,7 +368,7 @@ class TrLinear(TrCommon2):
class TrOchi(TrCommon2):
__doc__ = TrCommon2.__doc__.replace('<generic>', 'Ochi' #@ReservedAssignment
__doc__ = TrCommon2.__doc__.replace('<generic>', 'Ochi' # @ReservedAssignment
) + """
Description
@ -401,7 +398,8 @@ class TrOchi(TrCommon2):
Note
----
Transformation, g, does not have continous derivatives of 2'nd order or higher.
Transformation, g, does not have continous derivatives of 2'nd order or
higher.
Example
-------
@ -445,7 +443,7 @@ class TrOchi(TrCommon2):
return
# Solve the equations to obtain the gamma parameters:
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# a*(sig2^2+ma2^2)+ma2 = 0
# sig2^2-2*a^2*sig2^4 = E(y^2) % =1
# 2*a*sig2^4*(3-8*a^2*sig2^2) = E(y^3) % = skew
@ -454,22 +452,22 @@ class TrOchi(TrCommon2):
# Set up the 2D non-linear equations for a and sig2^2:
# g1='[x(2)-2.*x(1).^2.*x(2).^2-P1, 2.*x(1).*x(2).^2.*(3-8.*x(1).^2.*x(2))-P2 ]'
# Or solve the following 1D non-linear equation for sig2^2:
g2 = lambda x:-sqrt(abs(x - 1) * 2) * (3. * x - 4 * abs(x - 1)) + abs(skew)
g2 = lambda x: -sqrt(abs(x - 1) * 2) * \
(3. * x - 4 * abs(x - 1)) + abs(skew)
a1 = 1. # % Start interval where sig2^2 is located.
a2 = 2.
sig22 = brentq(g2, a1, a2) #% smallest solution for sig22
sig22 = brentq(g2, a1, a2) # % smallest solution for sig22
a = sign(skew) * sqrt(abs(sig22 - 1) / 2) / sig22
gam_a = 1.28 * a
gam_b = 3 * a
sigma2 = sqrt(sig22)
#% Solve the following 2nd order equation to obtain ma2
#% a*(sig2^2+ma2^2)+ma2 = 0
my2 = (-1. - sqrt(1. - 4. * a ** 2 * sig22)) / a #% Largest mean
mean2 = a * sig22 / my2 #% choose the smallest mean
# Solve the following 2nd order equation to obtain ma2
# a*(sig2^2+ma2^2)+ma2 = 0
my2 = (-1. - sqrt(1. - 4. * a ** 2 * sig22)) / a # % Largest mean
mean2 = a * sig22 / my2 # % choose the smallest mean
self._phat = [sigma1, mean1, gam_a, gam_b, sigma2, mean2]
return
@ -481,8 +479,8 @@ class TrOchi(TrCommon2):
if (self._phat is None or self.sigma != self._phat[0]
or self.mean != self._phat[1]):
self._par_from_stats()
#sigma1 = self._phat[0]
#mean1 = self._phat[1]
# sigma1 = self._phat[0]
# mean1 = self._phat[1]
ga = self._phat[2]
gb = self._phat[3]
sigma2 = self._phat[4]
@ -535,25 +533,23 @@ class TrOchi(TrCommon2):
xn.shape = yn.shape
return sigma * xn + mean
def main():
import pylab
g = TrHermite(skew=0.1, kurt=3.01)
g.dist2gauss()
#g = TrOchi(skew=0.56)
# g = TrOchi(skew=0.56)
x = np.linspace(-5, 5)
y = g(x)
pylab.plot(np.abs(x - g.gauss2dat(y)))
#pylab.plot(x,y,x,x,':',g.gauss2dat(y),y,'r')
# pylab.plot(x,y,x,x,':',g.gauss2dat(y),y,'r')
pylab.show()
np.disp('finito')
if __name__ == '__main__':
if True : # False: #
if True: # False: #
import doctest
doctest.testmod()
else:
main()

@ -3,33 +3,40 @@ from graphutil import cltext
from plotbackend import plotbackend
from time import gmtime, strftime
import numpy as np
from scipy.integrate.quadrature import cumtrapz #@UnresolvedImport
from scipy.integrate.quadrature import cumtrapz # @UnresolvedImport
from scipy.interpolate import griddata
from scipy import integrate
__all__ = ['PlotData', 'AxisLabels']
def empty_copy(obj):
class Empty(obj.__class__):
def __init__(self):
pass
newcopy = Empty()
newcopy.__class__ = obj.__class__
return newcopy
def _set_seed(iseed):
if iseed != None:
try:
np.random.set_state(iseed)
except:
np.random.seed(iseed)
def now():
'''
Return current date and time as a string
'''
return strftime("%a, %d %b %Y %H:%M:%S", gmtime())
class PlotData(object):
'''
Container class for data objects in WAFO
@ -66,6 +73,7 @@ class PlotData(object):
specdata,
covdata
'''
def __init__(self, data=None, args=None, *args2, **kwds):
self.data = data
self.args = args
@ -82,7 +90,7 @@ class PlotData(object):
self.setplotter(kwds.get('plotmethod', None))
def plot(self, *args, **kwds):
axis = kwds.pop('axis',None)
axis = kwds.pop('axis', None)
if axis is None:
axis = plotbackend.gca()
tmp = None
@ -90,7 +98,8 @@ class PlotData(object):
if not plotflag and self.children != None:
plotbackend.hold('on')
tmp = []
child_args = kwds.pop('plot_args_children', tuple(self.plot_args_children))
child_args = kwds.pop(
'plot_args_children', tuple(self.plot_args_children))
child_kwds = dict(self.plot_kwds_children).copy()
child_kwds.update(kwds.pop('plot_kwds_children', {}))
child_kwds['axis'] = axis
@ -127,9 +136,9 @@ class PlotData(object):
Unless you fix this, the plot methods will not work!'''
warnings.warn(msg)
else:
return griddata(self.args, self.data.ravel(), *args,**kwds)
else: #One dimensional data
return griddata((self.args,), self.data, *args,**kwds)
return griddata(self.args, self.data.ravel(), *args, **kwds)
else: # One dimensional data
return griddata((self.args,), self.data, *args, **kwds)
def integrate(self, a, b, **kwds):
'''
@ -139,7 +148,7 @@ class PlotData(object):
0.99940054759302188
'''
method = kwds.pop('method','trapz')
method = kwds.pop('method', 'trapz')
fun = getattr(integrate, method)
if isinstance(self.args, (list, tuple)): # Multidimensional data
ndim = len(self.args)
@ -152,15 +161,15 @@ class PlotData(object):
warnings.warn(msg)
else:
return griddata(self.args, self.data.ravel(), **kwds)
else: #One dimensional data
else: # One dimensional data
x = self.args
ix = np.flatnonzero((a<x) & (x<b) )
ix = np.flatnonzero((a < x) & (x < b))
xi = np.hstack((a, x.take(ix), b))
fi = np.hstack((self.eval_points(a),self.data.take(ix),self.eval_points(b)))
fi = np.hstack(
(self.eval_points(a), self.data.take(ix), self.eval_points(b)))
return fun(fi, xi, **kwds)
def show(self):
self.plotter.show()
@ -187,20 +196,24 @@ class PlotData(object):
else:
warnings.warn('Plotter method not implemented for ndim>2')
else: #One dimensional data
else: # One dimensional data
self.plotter = Plotter_1d(plotmethod)
class AxisLabels:
def __init__(self, title='', xlab='', ylab='', zlab='', **kwds):
self.title = title
self.xlab = xlab
self.ylab = ylab
self.zlab = zlab
def __repr__(self):
return self.__str__()
def __str__(self):
return '%s\n%s\n%s\n%s\n' % (self.title, self.xlab, self.ylab, self.zlab)
def copy(self):
newcopy = empty_copy(self)
newcopy.__dict__.update(self.__dict__)
@ -218,7 +231,9 @@ class AxisLabels:
except:
pass
class Plotter_1d(object):
"""
Parameters
@ -235,6 +250,7 @@ class Plotter_1d(object):
step : stair-step plot
scatter : scatter plot
"""
def __init__(self, plotmethod='plot'):
self.plotfun = None
if plotmethod is None:
@ -250,7 +266,7 @@ class Plotter_1d(object):
plotbackend.show()
def plot(self, wdata, *args, **kwds):
axis = kwds.pop('axis',None)
axis = kwds.pop('axis', None)
if axis is None:
axis = plotbackend.gca()
plotflag = kwds.pop('plotflag', False)
@ -277,6 +293,7 @@ class Plotter_1d(object):
h1 = plot1d(axis, x, data, dataCI, plotflag, *args, **kwds)
return h1
def plot1d(axis, args, data, dataCI, plotflag, *varargin, **kwds):
plottype = np.mod(plotflag, 10)
@ -289,18 +306,20 @@ def plot1d(axis, args, data, dataCI, plotflag, *varargin, **kwds):
elif plottype == 3:
H = axis.stem(args, data, *varargin, **kwds)
elif plottype == 4:
H = axis.errorbar(args, data, yerr=[dataCI[:,0] - data, dataCI[:,1] - data], *varargin, **kwds)
H = axis.errorbar(
args, data, yerr=[dataCI[:, 0] - data, dataCI[:, 1] - data], *varargin, **kwds)
elif plottype == 5:
H = axis.bar(args, data, *varargin, **kwds)
elif plottype == 6:
level = 0
if np.isfinite(level):
H = axis.fill_between(args, data, level, *varargin, **kwds);
H = axis.fill_between(args, data, level, *varargin, **kwds)
else:
H = axis.fill_between(args, data, *varargin, **kwds);
elif plottype==7:
H = axis.fill_between(args, data, *varargin, **kwds)
elif plottype == 7:
H = axis.plot(args, data, *varargin, **kwds)
H = axis.fill_between(args, dataCI[:,0], dataCI[:,1], alpha=0.2, color='r');
H = axis.fill_between(
args, dataCI[:, 0], dataCI[:, 1], alpha=0.2, color='r')
scale = plotscale(plotflag)
logXscale = 'x' in scale
@ -323,16 +342,17 @@ def plot1d(axis, args, data, dataCI, plotflag, *varargin, **kwds):
ax[3] = 11 * np.log10(fmax1)
ax[2] = ax[3] - 40
else:
ax[3] = 1.15 * fmax1;
ax[2] = ax[3] * 1e-4;
ax[3] = 1.15 * fmax1
ax[2] = ax[3] * 1e-4
axis.axis(ax)
if np.any(dataCI) and plottype < 3:
axis.hold(True)
plot1d(axis, args, dataCI, (), plotflag, 'r--');
plot1d(axis, args, dataCI, (), plotflag, 'r--')
return H
def plotscale(plotflag):
'''
Return plotscale from plotflag
@ -388,10 +408,12 @@ def plotscale(plotflag):
logZscaleId = (np.mod(scaleId // 100, 10) > 0) * 4
scaleId = logYscaleId + logXscaleId + logZscaleId
scales = ['linear', 'xlog', 'ylog', 'xylog', 'zlog', 'xzlog', 'yzlog', 'xyzlog']
scales = ['linear', 'xlog', 'ylog', 'xylog',
'zlog', 'xzlog', 'yzlog', 'xyzlog']
return scales[scaleId]
def transformdata(x, f, plotflag):
transFlag = np.mod(plotflag // 10, 10)
if transFlag == 0:
@ -407,11 +429,14 @@ def transformdata(x, f, plotflag):
data = -np.log1p(-cumtrapz(f, x))
else:
if any(f < 0):
raise ValueError('Invalid plotflag: Data or dataCI is negative, but must be positive')
raise ValueError(
'Invalid plotflag: Data or dataCI is negative, but must be positive')
data = 10 * np.log10(f)
return data
class Plotter_2d(Plotter_1d):
"""
Parameters
----------
@ -432,6 +457,7 @@ class Plotter_2d(Plotter_1d):
h1 = plot2d(axis, wdata, plotflag, *args, **kwds)
return h1
def plot2d(axis, wdata, plotflag, *args, **kwds):
f = wdata
if isinstance(wdata.args, (list, tuple)):
@ -440,7 +466,8 @@ def plot2d(axis, wdata, plotflag, *args, **kwds):
args1 = tuple((wdata.args,)) + (wdata.data,) + args
if plotflag in (1, 6, 7, 8, 9):
isPL = False
if hasattr(f, 'clevels') and len(f.clevels) > 0: # check if contour levels is submitted
# check if contour levels is submitted
if hasattr(f, 'clevels') and len(f.clevels) > 0:
CL = f.clevels
isPL = hasattr(f, 'plevels') and f.plevels is not None
if isPL:
@ -448,22 +475,25 @@ def plot2d(axis, wdata, plotflag, *args, **kwds):
else:
dmax = np.max(f.data)
dmin = np.min(f.data)
CL = dmax - (dmax - dmin) * (1 - np.r_[0.01, 0.025, 0.05, 0.1, 0.2, 0.4, 0.5, 0.75])
CL = dmax - (dmax - dmin) * \
(1 - np.r_[0.01, 0.025, 0.05, 0.1, 0.2, 0.4, 0.5, 0.75])
clvec = np.sort(CL)
if plotflag in [1, 8, 9]:
h = axis.contour(*args1, levels=CL, **kwds);
#else:
h = axis.contour(*args1, levels=CL, **kwds)
# else:
# [cs hcs] = contour3(f.x{:},f.f,CL,sym);
if plotflag in (1, 6):
ncl = len(clvec)
if ncl > 12:
ncl = 12
warnings.warn('Only the first 12 levels will be listed in table.')
warnings.warn(
'Only the first 12 levels will be listed in table.')
clvals = PL[:ncl] if isPL else clvec[:ncl]
unused_axcl = cltext(clvals, percent=isPL) # print contour level text
# print contour level text
unused_axcl = cltext(clvals, percent=isPL)
elif any(plotflag == [7, 9]):
axis.clabel(h)
else:
@ -471,45 +501,52 @@ def plot2d(axis, wdata, plotflag, *args, **kwds):
elif plotflag == 2:
h = axis.mesh(*args1, **kwds)
elif plotflag == 3:
h = axis.surf(*args1, **kwds) #shading interp % flat, faceted % surfc
# shading interp % flat, faceted % surfc
h = axis.surf(*args1, **kwds)
elif plotflag == 4:
h = axis.waterfall(*args1, **kwds)
elif plotflag == 5:
h = axis.pcolor(*args1, **kwds) #%shading interp % flat, faceted
h = axis.pcolor(*args1, **kwds) # %shading interp % flat, faceted
elif plotflag == 10:
h = axis.contourf(*args1, **kwds)
axis.clabel(h)
plotbackend.colorbar(h)
else:
raise ValueError('unknown option for plotflag')
#if any(plotflag==(2:5))
# if any(plotflag==(2:5))
# shading(shad);
#end
# end
# pass
def test_eval_points():
plotbackend.ioff()
x = np.linspace(0,5,21)
d = PlotData(np.sin(x),x)
xi = np.linspace(0,5,61)
di = PlotData(d.eval_points(xi,method='cubic'),xi)
x = np.linspace(0, 5, 21)
d = PlotData(np.sin(x), x)
xi = np.linspace(0, 5, 61)
di = PlotData(d.eval_points(xi, method='cubic'), xi)
d.plot('.')
di.plot()
di.show()
def test_integrate():
x = np.linspace(0,5,60)
x = np.linspace(0, 5, 60)
d = PlotData(np.sin(x), x)
print(d.integrate(0,np.pi/2,method='simps'))
print(d.integrate(0, np.pi / 2, method='simps'))
def test_docstrings():
import doctest
doctest.testmod()
def main():
pass
if __name__ == '__main__':
#test_integrate()
#test_eval_points()
# test_integrate()
# test_eval_points()
test_docstrings()
#main()
# main()

@ -5,9 +5,10 @@ Created on 3. juni 2011
'''
import numpy as np
from numpy import exp, expm1, inf, nan, pi, hstack, where, atleast_1d, cos, sin
from dispersion_relation import w2k, k2w #@UnusedImport
from dispersion_relation import w2k, k2w # @UnusedImport
__all__ = ['w2k', 'k2w', 'sensor_typeid', 'sensor_type', 'TransferFunction']
__all__ =['w2k', 'k2w', 'sensor_typeid', 'sensor_type', 'TransferFunction']
def hyperbolic_ratio(a, b, sa, sb):
'''
@ -19,7 +20,8 @@ def hyperbolic_ratio(a, b, sa, sb):
a, b : array-like
arguments vectors of the same size
sa, sb : scalar integers
defining the hyperbolic function used, i.e., f(x,1)=cosh(x), f(x,-1)=sinh(x)
defining the hyperbolic function used, i.e.,
f(x,1)=cosh(x), f(x,-1)=sinh(x)
Returns
-------
@ -53,7 +55,7 @@ def hyperbolic_ratio(a, b, sa, sb):
ak, bk, sak, sbk = np.atleast_1d(a, b, np.sign(sa), np.sign(sb))
# old call
#return exp(ak-bk)*(1+sak*exp(-2*ak))/(1+sbk*exp(-2*bk))
# return exp(ak-bk)*(1+sak*exp(-2*ak))/(1+sbk*exp(-2*bk))
# TODO: Does not always handle division by zero correctly
signRatio = np.where(sak * ak < 0, sak, 1)
@ -68,7 +70,9 @@ def hyperbolic_ratio(a, b, sa, sb):
ind = np.flatnonzero(den != 0)
iden.flat[ind] = 1.0 / den[ind]
val = np.where(num == den, 1, num * iden)
return signRatio * exp(ak - bk) * val #((sak+exp(-2*ak))/(sbk+exp(-2*bk)))
# ((sak+exp(-2*ak))/(sbk+exp(-2*bk)))
return signRatio * exp(ak - bk) * val
def sensor_typeid(*sensortypes):
''' Return ID for sensortype name
@ -97,9 +101,9 @@ def sensor_typeid(*sensortypes):
12, 'U_t' : Water particle acceleration in x-direction
13, 'V_t' : Water particle acceleration in y-direction
14, 'W_t' : Water particle acceleration in z-direction
15, 'X_p' : Water particle displacement in x-direction from its mean position
16, 'Y_p' : Water particle displacement in y-direction from its mean position
17, 'Z_p' : Water particle displacement in z-direction from its mean position
15, 'X_p' : Water particle displacement in x-direction from mean pos.
16, 'Y_p' : Water particle displacement in y-direction from mean pos.
17, 'Z_p' : Water particle displacement in z-direction from mean pos.
Example:
>>> sensor_typeid('W','v')
@ -121,7 +125,6 @@ def sensor_typeid(*sensortypes):
raise ValueError('Input must be a string!')
def sensor_type(*sensorids):
'''
Return sensortype name
@ -149,9 +152,9 @@ def sensor_type(*sensorids):
12, 'U_t' : Water particle acceleration in x-direction
13, 'V_t' : Water particle acceleration in y-direction
14, 'W_t' : Water particle acceleration in z-direction
15, 'X_p' : Water particle displacement in x-direction from its mean position
16, 'Y_p' : Water particle displacement in y-direction from its mean position
17, 'Z_p' : Water particle displacement in z-direction from its mean position
15, 'X_p' : Water particle displacement in x-direction from mean pos.
16, 'Y_p' : Water particle displacement in y-direction from mean pos.
17, 'Z_p' : Water particle displacement in z-direction from mean pos.
Example:
>>> sensor_type(range(3))
@ -162,16 +165,18 @@ def sensor_type(*sensorids):
sensor_typeid, tran
'''
valid_names = ('n', 'n_t', 'n_tt', 'n_x', 'n_y', 'n_xx', 'n_yy', 'n_xy',
'p', 'u', 'v', 'w', 'u_t', 'v_t', 'w_t', 'x_p', 'y_p', 'z_p',
nan)
'p', 'u', 'v', 'w', 'u_t', 'v_t', 'w_t', 'x_p', 'y_p',
'z_p', nan)
ids = atleast_1d(*sensorids)
if isinstance(ids, list):
ids = hstack(ids)
n = len(valid_names) - 1
ids = where(((ids < 0) | (n < ids)), n , ids)
ids = where(((ids < 0) | (n < ids)), n, ids)
return tuple(valid_names[i] for i in ids)
class TransferFunction(object):
'''
Class for computing transfer functions based on linear wave theory
of the system with input surface elevation,
@ -189,8 +194,8 @@ class TransferFunction(object):
( theta = 0 -> positive x axis theta = pi/2 -> positive y axis)
Member variables
----------------
pos : [x,y,z]
vector giving coordinate position relative to [x0 y0 z0] (default [0,0,0])
pos : [x,y,z], (default [0,0,0])
vector giving coordinate position relative to [x0 y0 z0]
sensortype = string
defining the sensortype or transfer function in output.
0, 'n' : Surface elevation (n=Eta) (default)
@ -208,17 +213,17 @@ class TransferFunction(object):
12, 'U_t' : Water particle acceleration in x-direction
13, 'V_t' : Water particle acceleration in y-direction
14, 'W_t' : Water particle acceleration in z-direction
15, 'X_p' : Water particle displacement in x-direction from its mean position
16, 'Y_p' : Water particle displacement in y-direction from its mean position
17, 'Z_p' : Water particle displacement in z-direction from its mean position
15, 'X_p' : Water particle displacement in x-direction from mean pos.
16, 'Y_p' : Water particle displacement in y-direction from mean pos.
17, 'Z_p' : Water particle displacement in z-direction from mean pos.
h : real scalar
water depth (default inf)
g : real scalar
acceleration of gravity (default 9.81 m/s**2)
rho : real scalar
water density (default 1028 kg/m**3)
bet : 1 or -1
1, theta given in terms of directions toward which waves travel (default)
bet : 1 or -1 (default 1)
1, theta given in terms of directions toward which waves travel
-1, theta given in terms of directions from which waves come
igam : 1,2 or 3
1, if z is measured positive upward from mean water level (default)
@ -243,9 +248,9 @@ class TransferFunction(object):
... tf.sensortype = stype
... Hw, Gwt = tf.tran(w0,th0)
... vals.append((Hw*Gwt*eta0).real.ravel())
... vals[i]
... fh = plt.plot(t, vals[i])
>>> plt.show()
fh = plt.plot(t, vals[i])
plt.show()
See also
@ -258,10 +263,12 @@ class TransferFunction(object):
"On the measurement of directional spectra",
Applied Ocean Research, Vol 16, pp 283-294
'''
def __init__(self, pos=(0, 0, 0), sensortype='n', h=inf, g=9.81, rho=1028,
bet=1, igam=1, thetax=90, thetay=0):
self.pos = pos
self.sensortype = sensortype if isinstance(sensortype, str) else sensor_type(sensortype)
self.sensortype = sensortype if isinstance(
sensortype, str) else sensor_type(sensortype)
self.h = h
self.g = g
self.rho = rho
@ -299,8 +306,8 @@ class TransferFunction(object):
vector of directions in radians Length Nt (default 0)
( theta = 0 -> positive x axis theta = pi/2 -> positive y axis)
kw : array-like
vector of wave numbers corresponding to angular frequencies, w. Length Nf
(default calculated with w2k)
vector of wave numbers corresponding to angular frequencies, w.
Length Nf (default calculated with w2k)
Returns
-------
@ -311,7 +318,8 @@ class TransferFunction(object):
w (columns) and theta (rows) size Nt x Nf
'''
if kw is None:
kw, unusedkw2 = w2k(w, 0, self.h) #wave number as function of angular frequency
# wave number as function of angular frequency
kw, unusedkw2 = w2k(w, 0, self.h)
w, theta, kw = np.atleast_1d(w, theta, kw)
# make sure they have the correct orientation
@ -327,19 +335,21 @@ class TransferFunction(object):
ind = np.flatnonzero(1 - np.isfinite(Hw))
Hw.flat[ind] = 0
sgn = np.sign(Hw);
sgn = np.sign(Hw)
k0 = np.flatnonzero(sgn < 0)
if len(k0): # make sure Hw>=0 ie. transfer negative signs to Gwt
Gwt[:, k0] = -Gwt[:, k0]
Hw[:, k0] = -Hw[:, k0]
if self.igam == 2:
#pab 09 Oct.2002: bug fix
# Changing igam by 2 should affect the directional result in the same way that changing eta by -eta!
# pab 09 Oct.2002: bug fix
# Changing igam by 2 should affect the directional result in the
# same way that changing eta by -eta!
Gwt = -Gwt
return Hw, Gwt
__call__ = tran
#---Private member methods
def _get_ee_cthxy(self, theta, kw):
# convert from angle in degrees to radians
bet = self.bet
@ -352,16 +362,19 @@ class TransferFunction(object):
# Compute location complex exponential
x, y, unused_z = list(self.pos)
ee = exp((1j * (x * cthx + y * cthy)) * kw) # exp(i*k(w)*(x*cos(theta)+y*sin(theta)) size Nt X Nf
# exp(i*k(w)*(x*cos(theta)+y*sin(theta)) size Nt X Nf
ee = exp((1j * (x * cthx + y * cthy)) * kw)
return ee, cthx, cthy
def _get_zk(self, kw):
h = self.h
z = self.pos[2]
if self.igam == 1:
zk = kw * (h + z) # z measured positive upward from mean water level (default)
# z measured positive upward from mean water level (default)
zk = kw * (h + z)
elif self.igam == 2:
zk = kw * (h - z) # z measured positive downward from mean water level
# z measured positive downward from mean water level
zk = kw * (h - z)
else:
zk = kw * z # z measured positive upward from sea floor
return zk
@ -377,7 +390,8 @@ class TransferFunction(object):
def _n_t(self, w, theta, kw):
''' n_t = Eta_t '''
ee, unused_cthx, unused_cthy = self._get_ee_cthxy(theta, kw)
return w, -1j * ee;
return w, -1j * ee
def _n_tt(self, w, theta, kw):
'''n_tt = Eta_tt'''
ee, unused_cthx, unused_cthy = self._get_ee_cthxy(theta, kw)
@ -388,6 +402,7 @@ class TransferFunction(object):
''' n_x = Eta_x = x-slope'''
ee, cthx, unused_cthy = self._get_ee_cthxy(theta, kw)
return kw, 1j * cthx * ee
def _n_y(self, w, theta, kw):
''' n_y = Eta_y = y-slope'''
ee, unused_cthx, cthy = self._get_ee_cthxy(theta, kw)
@ -398,10 +413,12 @@ class TransferFunction(object):
''' n_xx = Eta_xx = Surface curvature (x-dir)'''
ee, cthx, unused_cthy = self._get_ee_cthxy(theta, kw)
return kw ** 2, -(cthx ** 2) * ee
def _n_yy(self, w, theta, kw):
''' n_yy = Eta_yy = Surface curvature (y-dir)'''
ee, unused_cthx, cthy = self._get_ee_cthxy(theta, kw)
return kw ** 2, -cthy ** 2 * ee
def _n_xy(self, w, theta, kw):
''' n_xy = Eta_xy = Surface curvature (xy-dir)'''
ee, cthx, cthy = self._get_ee_cthxy(theta, kw)
@ -413,7 +430,8 @@ class TransferFunction(object):
ee, unused_cthx, unused_cthy = self._get_ee_cthxy(theta, kw)
hk = kw * self.h
zk = self._get_zk(kw)
return self.rho * self.g * hyperbolic_ratio(zk, hk, 1, 1), ee #hyperbolic_ratio = cosh(zk)/cosh(hk)
# hyperbolic_ratio = cosh(zk)/cosh(hk)
return self.rho * self.g * hyperbolic_ratio(zk, hk, 1, 1), ee
#---- Water particle velocities ---
def _u(self, w, theta, kw):
@ -421,19 +439,24 @@ class TransferFunction(object):
ee, cthx, unused_cthy = self._get_ee_cthxy(theta, kw)
hk = kw * self.h
zk = self._get_zk(kw)
return w * hyperbolic_ratio(zk, hk, 1, -1), cthx * ee# w*cosh(zk)/sinh(hk), cos(theta)*ee
# w*cosh(zk)/sinh(hk), cos(theta)*ee
return w * hyperbolic_ratio(zk, hk, 1, -1), cthx * ee
def _v(self, w, theta, kw):
'''V = y-velocity'''
ee, unused_cthx, cthy = self._get_ee_cthxy(theta, kw)
hk = kw * self.h
zk = self._get_zk(kw)
return w * hyperbolic_ratio(zk, hk, 1, -1), cthy * ee # w*cosh(zk)/sinh(hk), sin(theta)*ee
# w*cosh(zk)/sinh(hk), sin(theta)*ee
return w * hyperbolic_ratio(zk, hk, 1, -1), cthy * ee
def _w(self, w, theta, kw):
''' W = z-velocity'''
ee, unused_cthx, unused_cthy = self._get_ee_cthxy(theta, kw)
hk = kw * self.h
zk = self._get_zk(kw)
return w * hyperbolic_ratio(zk, hk, -1, -1), -1j * ee # w*sinh(zk)/sinh(hk), -?
# w*sinh(zk)/sinh(hk), -?
return w * hyperbolic_ratio(zk, hk, -1, -1), -1j * ee
#---- Water particle acceleration ---
def _u_t(self, w, theta, kw):
@ -441,20 +464,24 @@ class TransferFunction(object):
ee, cthx, unused_cthy = self._get_ee_cthxy(theta, kw)
hk = kw * self.h
zk = self._get_zk(kw)
return (w ** 2) * hyperbolic_ratio(zk, hk, 1, -1), -1j * cthx * ee # w^2*cosh(zk)/sinh(hk), ?
# w^2*cosh(zk)/sinh(hk), ?
return (w ** 2) * hyperbolic_ratio(zk, hk, 1, -1), -1j * cthx * ee
def _v_t(self, w, theta, kw):
''' V_t = y-acceleration'''
ee, unused_cthx, cthy = self._get_ee_cthxy(theta, kw)
hk = kw * self.h
zk = self._get_zk(kw)
return (w ** 2) * hyperbolic_ratio(zk, hk, 1, -1), -1j * cthy * ee # w^2*cosh(zk)/sinh(hk), ?
# w^2*cosh(zk)/sinh(hk), ?
return (w ** 2) * hyperbolic_ratio(zk, hk, 1, -1), -1j * cthy * ee
def _w_t(self, w, theta, kw):
''' W_t = z-acceleration'''
ee, unused_cthx, unused_cthy = self._get_ee_cthxy(theta, kw)
hk = kw * self.h
zk = self._get_zk(kw)
return (w ** 2) * hyperbolic_ratio(zk, hk, -1, -1), -ee # w*sinh(zk)/sinh(hk), ?
# w*sinh(zk)/sinh(hk), ?
return (w ** 2) * hyperbolic_ratio(zk, hk, -1, -1), -ee
#---- Water particle displacement ---
def _x_p(self, w, theta, kw):
@ -462,13 +489,17 @@ class TransferFunction(object):
ee, cthx, unused_cthy = self._get_ee_cthxy(theta, kw)
hk = kw * self.h
zk = self._get_zk(kw)
return hyperbolic_ratio(zk, hk, 1, -1), 1j * cthx * ee # cosh(zk)./sinh(hk), ?
# cosh(zk)./sinh(hk), ?
return hyperbolic_ratio(zk, hk, 1, -1), 1j * cthx * ee
def _y_p(self, w, theta, kw):
''' Y_p = y-displacement'''
ee, unused_cthx, cthy = self._get_ee_cthxy(theta, kw)
hk = kw * self.h
zk = self._get_zk(kw)
return hyperbolic_ratio(zk, hk, 1, -1), 1j * cthy * ee # cosh(zk)./sinh(hk), ?
# cosh(zk)./sinh(hk), ?
return hyperbolic_ratio(zk, hk, 1, -1), 1j * cthy * ee
def _z_p(self, w, theta, kw):
''' Z_p = z-displacement'''
ee, unused_cthx, unused_cthy = self._get_ee_cthxy(theta, kw)
@ -476,7 +507,7 @@ class TransferFunction(object):
zk = self._get_zk(kw)
return hyperbolic_ratio(zk, hk, -1, -1), ee # sinh(zk)./sinh(hk), ee
#def wave_pressure(z, Hm0, h=10000, g=9.81, rho=1028):
# def wave_pressure(z, Hm0, h=10000, g=9.81, rho=1028):
# '''
# Calculate pressure amplitude due to water waves.
#
@ -531,7 +562,7 @@ class TransferFunction(object):
# '''
#
#
# # Assume seastate with jonswap spectrum:
# Assume seastate with jonswap spectrum:
#
# Tp = 4 * np.sqrt(Hm0)
# gam = jonswap_peakfact(Hm0, Tp)
@ -542,13 +573,13 @@ class TransferFunction(object):
# hk = kw * h
# zk1 = kw * z
# zk = hk + zk1 # z measured positive upward from mean water level (default)
# #zk = hk-zk1; % z measured positive downward from mean water level
# #zk1 = -zk1;
# #zk = zk1; % z measured positive upward from sea floor
# zk = hk-zk1; % z measured positive downward from mean water level
# zk1 = -zk1;
# zk = zk1; % z measured positive upward from sea floor
#
# # cosh(zk)/cosh(hk) approx exp(zk) for large h
# # hyperbolic_ratio(zk,hk,1,1) = cosh(zk)/cosh(hk)
# # pr = np.where(np.pi < hk, np.exp(zk1), hyperbolic_ratio(zk, hk, 1, 1))
# cosh(zk)/cosh(hk) approx exp(zk) for large h
# hyperbolic_ratio(zk,hk,1,1) = cosh(zk)/cosh(hk)
# pr = np.where(np.pi < hk, np.exp(zk1), hyperbolic_ratio(zk, hk, 1, 1))
# pr = hyperbolic_ratio(zk, hk, 1, 1)
# pressure = (rho * g * Hm0 / 2) * pr
#
@ -559,7 +590,14 @@ class TransferFunction(object):
#
# return pressure
def test_docstrings():
import doctest
print('Testing docstrings in %s' % __file__)
doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
def main():
sensor_type(range(21))
if __name__ == '__main__':
pass
test_docstrings()

@ -6,11 +6,13 @@ w2k - Translates from frequency to wave number
"""
import warnings
#import numpy as np
from numpy import (atleast_1d, sqrt, ones_like, zeros_like, arctan2, where, tanh, any, #@UnresolvedImport
sin, cos, sign, inf, flatnonzero, finfo, cosh, abs) #@UnresolvedImport
from numpy import (atleast_1d, sqrt, ones_like, zeros_like, arctan2, where,
tanh, any, sin, cos, sign, inf,
flatnonzero, finfo, cosh, abs)
__all__ = ['k2w', 'w2k']
def k2w(k1, k2=0e0, h=inf, g=9.81, u1=0e0, u2=0e0):
''' Translates from wave number to frequency
using the dispersion relation
@ -53,7 +55,7 @@ def k2w(k1, k2=0e0, h=inf, g=9.81, u1=0e0, u2=0e0):
Example
-------
>>> from numpy import arange
>>> import wafo.spectrum.dispersion_relation as wsd
>>> import wafo.wave_theory.dispersion_relation as wsd
>>> wsd.k2w(arange(0.01,.5,0.2))[0]
array([ 0.3132092 , 1.43530485, 2.00551739])
>>> wsd.k2w(arange(0.01,.5,0.2),h=20)[0]
@ -64,15 +66,15 @@ def k2w(k1, k2=0e0, h=inf, g=9.81, u1=0e0, u2=0e0):
if k1i.size == 0:
return zeros_like(k1i)
ku1 = k1i*u1i
ku2 = k2i*u2i
ku1 = k1i * u1i
ku2 = k2i * u2i
theta = arctan2(k2, k1)
k = sqrt(k1i**2+k2i**2)
w = where(k>0, ku1+ku2+sqrt(gi*k*tanh(k*hi)), 0.0)
k = sqrt(k1i ** 2 + k2i ** 2)
w = where(k > 0, ku1 + ku2 + sqrt(gi * k * tanh(k * hi)), 0.0)
cond = (w<0)
cond = (w < 0)
if any(cond):
txt0 = '''
Waves and current are in opposite directions
@ -84,6 +86,7 @@ def k2w(k1, k2=0e0, h=inf, g=9.81, u1=0e0, u2=0e0):
return w, theta
def w2k(w, theta=0.0, h=inf, g=9.81, count_limit=100):
'''
Translates from frequency to wave number
@ -107,7 +110,8 @@ def w2k(w, theta=0.0, h=inf, g=9.81, count_limit=100):
Description
-----------
Uses Newton Raphson method to find the wave number k in the dispersion relation
Uses Newton Raphson method to find the wave number k in the dispersion
relation
w**2= g*k*tanh(k*h).
The solution k(w) => k1 = k(w)*cos(theta)
k2 = k(w)*sin(theta)
@ -118,7 +122,7 @@ def w2k(w, theta=0.0, h=inf, g=9.81, count_limit=100):
Example
-------
>>> import pylab as plb
>>> import wafo.spectrum.dispersion_relation as wsd
>>> import wafo.wave_theory.dispersion_relation as wsd
>>> w = plb.linspace(0,3);
>>> h = plb.plot(w,w2k(w)[0])
>>> wsd.w2k(range(4))[0]
@ -137,19 +141,15 @@ def w2k(w, theta=0.0, h=inf, g=9.81, count_limit=100):
if wi.size == 0:
return zeros_like(wi)
k = 1.0*sign(wi)*wi**2.0 / gi[0] # deep water
k = 1.0 * sign(wi) * wi ** 2.0 / gi[0] # deep water
if (hi > 10. ** 25).all():
k2 = k*sin(th)*gi[0]/gi[-1] #size np x nf
k1 = k*cos(th)
k2 = k * sin(th) * gi[0] / gi[-1] # size np x nf
k1 = k * cos(th)
return k1, k2
if gi.size > 1:
txt0 = '''
Finite depth in combination with 3D normalization (len(g)=2) is not implemented yet.
'''
raise ValueError(txt0)
raise ValueError('Finite depth in combination with 3D normalization' +
' (len(g)=2) is not implemented yet.')
find = flatnonzero
eps = finfo(float).eps
@ -161,46 +161,50 @@ def w2k(w, theta=0.0, h=inf, g=9.81, count_limit=100):
# Permit no more than count_limit iterations.
hi = hi * ones_like(k)
hn = zeros_like(k)
ix = find((wi<0) | (0<wi))
ix = find((wi < 0) | (0 < wi))
# Break out of the iteration loop for three reasons:
# 1) the last update is very small (compared to x)
# 2) the last update is very small (compared to sqrt(eps))
# 3) There are more than 100 iterations. This should NEVER happen.
count = 0
while (ix.size>0 and count < count_limit):
while (ix.size > 0 and count < count_limit):
ki = k[ix]
kh = ki * hi[ix]
hn[ix] = (ki*tanh(kh)-wi[ix]**2.0/gi)/(tanh(kh)+kh/(cosh(kh)**2.0))
hn[ix] = (ki * tanh(kh) - wi[ix] ** 2.0 / gi) / \
(tanh(kh) + kh / (cosh(kh) ** 2.0))
knew = ki - hn[ix]
# Make sure that the current guess is not zero.
# When Newton's Method suggests steps that lead to zero guesses
# take a step 9/10ths of the way to zero:
ksmall = find(abs(knew)==0)
if ksmall.size>0:
ksmall = find(abs(knew) == 0)
if ksmall.size > 0:
knew[ksmall] = ki[ksmall] / 10.0
hn[ix[ksmall]] = ki[ksmall]-knew[ksmall]
hn[ix[ksmall]] = ki[ksmall] - knew[ksmall]
k[ix] = knew
# disp(['Iteration ',num2str(count),' Number of points left: ' num2str(length(ix)) ]),
# disp(['Iteration ',num2str(count),' Number of points left: '
# num2str(length(ix)) ]),
ix = find((abs(hn) > sqrt(eps)*abs(k)) * abs(hn) > sqrt(eps))
ix = find((abs(hn) > sqrt(eps) * abs(k)) * abs(hn) > sqrt(eps))
count += 1
if count == count_limit:
txt1 = ''' W2K did not converge.
The maximum error in the last step was: %13.8f''' % max(hn[ix])
warnings.warn(txt1)
warnings.warn('W2K did not converge. The maximum error in the ' +
'last step was: %13.8f' % max(hn[ix]))
k.shape = oshape
k2 = k*sin(th)
k1 = k*cos(th)
k2 = k * sin(th)
k1 = k * cos(th)
return k1, k2
def main():
def test_docstrings():
import doctest
doctest.testmod()
print('Testing docstrings in %s' % __file__)
doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
if __name__ == '__main__':
main()
test_docstrings()

@ -4,27 +4,31 @@ Created on 19. juli 2010
@author: pab
'''
import numpy as np
from wafo.wave_theory.dispersion_relation import w2k,k2w #@UnusedImport
from wafo.wave_theory.dispersion_relation import w2k, k2w # @UnusedImport
def test_k2w_infinite_water_depth():
vals = k2w(np.arange(0.01,.5,0.2))[0]
true_vals = np.array([ 0.3132092 , 1.43530485, 2.00551739])
assert((np.abs(vals-true_vals)<1e-7).all())
vals = k2w(np.arange(0.01, .5, 0.2))[0]
true_vals = np.array([0.3132092, 1.43530485, 2.00551739])
assert((np.abs(vals - true_vals) < 1e-7).all())
def test_k2w_finite_water_depth():
vals = k2w(np.arange(0.01,.5,0.2),h=20)[0]
true_vals = np.array([ 0.13914927, 1.43498213, 2.00551724])
assert((np.abs(vals-true_vals)<1e-7).all())
vals = k2w(np.arange(0.01, .5, 0.2), h=20)[0]
true_vals = np.array([0.13914927, 1.43498213, 2.00551724])
assert((np.abs(vals - true_vals) < 1e-7).all())
def test_w2k_infinite_water_depth():
vals = w2k(range(4))[0]
true_vals = np.array([ 0. , 0.1019368 , 0.4077472 , 0.91743119])
assert((np.abs(vals-true_vals)<1e-7).all())
true_vals = np.array([0., 0.1019368, 0.4077472, 0.91743119])
assert((np.abs(vals - true_vals) < 1e-7).all())
def test_w2k_finite_water_depth():
vals = w2k(range(4),h=20)[0]
true_vals = np.array([ 0. , 0.10503601, 0.40774726, 0.91743119])
assert((np.abs(vals-true_vals)<1e-7).all())
vals = w2k(range(4), h=20)[0]
true_vals = np.array([0., 0.10503601, 0.40774726, 0.91743119])
assert((np.abs(vals - true_vals) < 1e-7).all())
if __name__ == '__main__':
import nose

Loading…
Cancel
Save