Added functionality to TimeSeries.trdata

master
per.andreas.brodtkorb 14 years ago
parent f5fcfce780
commit 3de75c6a43

@ -176,7 +176,7 @@ g = wtm.TrLinear(mean=me, sigma=sa ).trdata()
#! Linear transformation
glc, gemp = lc.trdata()
glc, gemp = lc.trdata(mean=me, sigma=sa)
g.plot('r')
glc.plot('b-') #! Transf. estimated from level-crossings
gh.plot('b-.') #! Hermite Transf. estimated from moments

@ -15,15 +15,18 @@
from __future__ import division
from wafo.transform.core import TrData
from wafo.transform.models import TrHermite, TrOchi, TrLinear
from wafo.stats import edf
from wafo.interpolate import SmoothSpline
from scipy.interpolate.interpolate import interp1d
from scipy.integrate.quadrature import cumtrapz #@UnresolvedImport
from scipy.special import ndtr as cdfnorm, ndtri as invnorm
import warnings
import numpy as np
from numpy import (inf, pi, zeros, ones, sqrt, where, log, exp, sin, arcsin, mod, finfo, interp, #@UnresolvedImport
newaxis, linspace, arange, sort, all, abs, vstack, hstack, atleast_1d, #@UnresolvedImport
polyfit, r_, nonzero, cumsum, ravel, size, isnan, nan, floor, ceil, diff, array) #@UnresolvedImport
finfo, polyfit, r_, nonzero, cumsum, ravel, size, isnan, nan, floor, ceil, diff, array) #@UnresolvedImport
from numpy.fft import fft
from numpy.random import randn
from scipy.integrate import trapz
@ -31,9 +34,6 @@ from pylab import stineman_interp
from matplotlib.mlab import psd, detrend_mean
import scipy.signal
from scipy.special import erf, ndtri
from wafo.misc import (nextpow2, findtp, findtc, findcross, sub_dict_select,
ecross, JITImport, DotDict)
from wafodata import WafoData
@ -43,6 +43,7 @@ from scipy.stats.stats import skew, kurtosis
from scipy.signal.windows import parzen
from scipy import special
floatinfo = finfo(float)
matplotlib.interactive(True)
_wafocov = JITImport('wafo.covariance')
_wafospec = JITImport('wafo.spectrum')
@ -187,7 +188,7 @@ class LevelCrossings(WafoData):
mini = -maxi
u = linspace(mini, maxi, 101)
G = (1 + erf(u / sqrt(2))) / 2
G = cdfnorm(u) #(1 + erf(u / sqrt(2))) / 2
G = G * (1 - G)
x = linspace(0, r1, 100)
@ -315,19 +316,19 @@ class LevelCrossings(WafoData):
>>> tp = ts.turning_points()
>>> mm = tp.cycle_pairs()
>>> lc = mm.level_crossings()
>>> g0, gemp = lc.trdata(monitor=True) # Monitor the development
>>> g1, gemp = lc.trdata(gvar=0.5 ) # Equal weight on all points
>>> g2, gemp = lc.trdata(gvar=[3.5, 0.5, 3.5]) # Less weight on the ends
>>> g0, g0emp = lc.trdata(monitor=True) # Monitor the development
>>> g1, g1emp = lc.trdata(gvar=0.5 ) # Equal weight on all points
>>> g2, g2emp = lc.trdata(gvar=[3.5, 0.5, 3.5]) # Less weight on the ends
>>> int(S.tr.dist2gauss()*100)
593
>>> int(gemp.dist2gauss()*100)
431
>>> int(g0emp.dist2gauss()*100)
492
>>> int(g0.dist2gauss()*100)
391
361
>>> int(g1.dist2gauss()*100)
311
352
>>> int(g2.dist2gauss()*100)
357
365
hold on, trplot(g1,g) # Check the fit
trplot(g2)
@ -357,7 +358,7 @@ class LevelCrossings(WafoData):
sigma = self.stdev
opt = DotDict(chkder=True, plotflag=False, csm=0.9, gsm=.05,
param=(-5, 5, 513), delay=2, lin_extrap=True, ntr=inf, ne=7, cvar=1, gvar=1)
param=(-5, 5, 513), delay=2, linextrap=True, ntr=inf, ne=7, cvar=1, gvar=1)
# If just 'defaults' passed in, return the default options in g
opt.update(options)
@ -411,7 +412,7 @@ class LevelCrossings(WafoData):
imax = abs(lc22 - 0.85).argmin()
inde = slice(imin, imax + 1)
lc222 = SmoothSpline(lc11[inde], g22[inde], opt.csm, opt.lin_extrap, cvar[inde])(lc11[inde])
lc222 = SmoothSpline(lc11[inde], g22[inde], opt.csm, opt.linextrap, cvar[inde])(lc11[inde])
#tmp = smooth(cros(inde,1),g2(inde,2),opt.csm,cros(inde,1),def,cvar(inde));
@ -420,18 +421,20 @@ class LevelCrossings(WafoData):
#u0 = interp1q(cros(:,2),cros(:,1),.5)
lc22 = ndtri(lc22) - u0 #invnorm(lc22, -u0, 1);
#lc22 = ndtri(lc22) - u0 #
lc22 = invnorm(lc22) - u0
g2 = TrData(lc22.copy(), lc1.copy(), mean, sigma ** 2)
g2 = TrData(lc22.copy(), lc1.copy(), mean=mean, sigma=sigma)
g2.setplotter('step')
# NB! the smooth function does not always extrapolate well outside the edges
# causing poor estimate of g
# We may alleviate this problem by: forcing the extrapolation
# to be linear outside the edges or choosing a lower value for csm2.
inds = slice(Ne, ncr - Ne) # indices to points we are smoothing over
scros2 = SmoothSpline(lc11[inds], lc22[inds], opt.gsm, opt.lin_extrap, gvar[inds])(uu)
scros2 = SmoothSpline(lc11[inds], lc22[inds], opt.gsm, opt.linextrap, gvar[inds])(uu)
g = TrData(scros2, g1, mean, sigma ** 2) #*sa; #multiply with stdev
g = TrData(scros2, g1, mean=mean, sigma=sigma) #*sa; #multiply with stdev
if opt.chkder:
for ix in range(5):
@ -444,14 +447,14 @@ class LevelCrossings(WafoData):
eps = finfo(float).eps
dy[dy > 0] = eps
gvar = -(hstack((dy, 0)) + hstack((0, dy))) / 2 + eps
g.data = SmoothSpline(g.args, g.data, 1, opt.lin_extrap, ix * gvar)(g.args)
g.data = SmoothSpline(g.args, g.data, 1, opt.linextrap, ix * gvar)(g.args)
else:
break
if opt.plotflag > 0:
g.plot()
g2.plot()
g2.setplotter('step')
return g, g2
class CyclePairs(WafoData):
@ -475,11 +478,11 @@ class CyclePairs(WafoData):
>>> h1 = mm.plot(marker='x')
'''
def __init__(self, *args, **kwds):
self.type_ = kwds.get('type_', 'max2min')
self.stdev = kwds.get('stdev', None)
self.mean = kwds.get('mean', None)
self.kind = kwds.pop('kind', 'max2min')
self.stdev = kwds.pop('stdev', None)
self.mean = kwds.pop('mean', None)
options = dict(title=self.type_ + ' cycle pairs',
options = dict(title=self.kind + ' cycle pairs',
xlab='min', ylab='max',
plot_args=['b.'])
options.update(**kwds)
@ -531,12 +534,12 @@ class CyclePairs(WafoData):
amp = abs(self.amplitudes())
return atleast_1d([K * np.sum(amp ** betai) for betai in beta])
def level_crossings(self, type_='uM'):
def level_crossings(self, kind='uM'):
""" Return number of upcrossings from a cycle count.
Parameters
----------
type_ : int or string
kind : int or string
defining crossing type, options are
0,'u' : only upcrossings.
1,'uM' : upcrossings and maxima (default).
@ -567,14 +570,14 @@ class CyclePairs(WafoData):
LevelCrossings
"""
if isinstance(type_, str):
if isinstance(kind, str):
t = dict(u=0, uM=1, umM=2, um=3)
defnr = t.get(type_, 1)
defnr = t.get(kind, 1)
else:
defnr = type_
defnr = kind
if ((defnr < 0) or (defnr > 3)):
raise ValueError('type_ must be one of (1,2,3,4).')
raise ValueError('kind must be one of (1,2,3,4).')
index, = nonzero(self.args <= self.data)
if index.size == 0:
@ -589,9 +592,7 @@ class CyclePairs(WafoData):
# error('Error in input cc.')
#end
ncc = len(m)
#ones = np.ones
#zeros = np.zeros
#cumsum = np.cumsum
minima = vstack((m, ones(ncc), zeros(ncc), ones(ncc)))
maxima = vstack((M, -ones(ncc), ones(ncc), zeros(ncc)))
@ -622,7 +623,7 @@ class CyclePairs(WafoData):
dcount = cumsum(extr[1, 0:nx]) - extr[3, 0:nx]
elif defnr == 3: ## This are upcrossings + minima + maxima
dcount = cumsum(extr[1, 0:nx]) + extr[2, 0:nx]
return LevelCrossings(dcount, levels, stdev=self.stdev)
return LevelCrossings(dcount, levels, mean=self.mean, stdev=self.stdev)
class TurningPoints(WafoData):
'''
@ -644,12 +645,15 @@ class TurningPoints(WafoData):
>>> h1 = tp.plot(marker='x')
'''
def __init__(self, *args, **kwds):
super(TurningPoints, self).__init__(*args, **kwds)
self.name = 'WAFO TurningPoints Object'
somekeys = ['name']
self.__dict__.update(sub_dict_select(kwds, somekeys))
self.name_ = kwds.pop('name', 'WAFO TurningPoints Object')
self.stdev = kwds.pop('stdev', None)
self.mean = kwds.pop('mean', None)
options = dict(title='Turning points')
#plot_args=['b.'])
options.update(**kwds)
super(TurningPoints, self).__init__(*args, **options)
#self.setlabels()
if not any(self.args):
n = len(self.data)
self.args = range(0, n)
@ -657,12 +661,12 @@ class TurningPoints(WafoData):
self.args = ravel(self.args)
self.data = ravel(self.data)
def cycle_pairs(self, type_='min2max'):
def cycle_pairs(self, kind='min2max'):
""" Return min2Max or Max2min cycle pairs from turning points
Parameters
----------
type_ : string
kind : string
type of cycles to return options are 'min2max' or 'max2min'
Return
@ -694,14 +698,14 @@ class TurningPoints(WafoData):
# Extract min-max and max-min cycle pairs
#n = len(self.data)
if type_.lower().startswith('min2max'):
if kind.lower().startswith('min2max'):
m = self.data[im:-1:2]
M = self.data[im + 1::2]
else:
type_ = 'max2min'
kind = 'max2min'
M = self.data[iM:-1:2]
m = self.data[iM + 1::2]
return CyclePairs(M, m, type=type_)
return CyclePairs(M, m, kind=kind, mean=self.mean, stdev=self.stdev)
def mat2timeseries(x):
"""
@ -735,6 +739,7 @@ class TimeSeries(WafoData):
>>> h = rf.plot()
>>> S = ts.tospecdata()
The default L is set to 68
>>> tp = ts.turning_points()
>>> mm = tp.cycle_pairs()
@ -745,14 +750,12 @@ class TimeSeries(WafoData):
'''
def __init__(self, *args, **kwds):
self.name_ = kwds.pop('name', 'WAFO TimeSeries Object')
self.sensortypes = kwds.pop('sensortypes',['n', ])
self.position = kwds.pop('position', [zeros(3), ])
super(TimeSeries, self).__init__(*args, **kwds)
self.name = 'WAFO TimeSeries Object'
self.sensortypes = ['n', ]
self.position = [zeros(3), ]
somekeys = ['sensortypes', 'position']
self.__dict__.update(sub_dict_select(kwds, somekeys))
#self.setlabels()
if not any(self.args):
n = len(self.data)
self.args = range(0, n)
@ -1047,27 +1050,93 @@ class TimeSeries(WafoData):
# S.S = zeros(nf+1,m-1);
return spec
def _trdata_cdf(self, **options):
'''
Estimate transformation, g, from observed marginal CDF.
Assumption: a Gaussian process, Y, is related to the
non-Gaussian process, X, by Y = g(X).
Parameters
----------
options = options structure defining how the smoothing is done.
(See troptset for default values)
Returns
-------
tr, tr_emp = smoothed and empirical estimate of the transformation g.
The empirical CDF is usually very irregular. More than one local
maximum of the empirical CDF may cause poor fit of the transformation.
In such case one should use a smaller value of GSM or set a larger
variance for GVAR. If X(t) is likely to cross levels higher than 5
standard deviations then the vector param has to be modified. For
example if X(t) is unlikely to cross a level of 7 standard deviations
one can use param = [-7 7 513].
def trdata(self, method='nonlinear', **options):
'''
Estimate transformation, g, from data.
CALL: [g test cmax irr g2] = dat2tr(x,def,options);
mean = self.data.mean()
sigma = self.data.std()
cdf = edf(self.data.ravel())
opt = DotDict(chkder=True, plotflag=False, gsm=0.05, param=[-5, 5, 513],
delay=2, linextrap=True, ntr=1000, ne=7, gvar=1)
opt.update(options)
Ne = opt.ne
nd = len(cdf.data)
if nd > opt.ntr and opt.ntr > 0:
x0 = linspace(cdf.args[Ne], cdf.args[nd - 1 - Ne], opt.ntr)
cdf.data = interp(x0, cdf.args, cdf.data)
cdf.args = x0
Ne = 0
uu = linspace(*opt.param)
ncr = len(cdf.data);
ng = len(np.atleast_1d(opt.gvar))
if ng == 1:
gvar = opt.gvar * ones(ncr)
else:
opt.gvar = np.atleast_1d(opt.gvar)
gvar = interp(linspace(0, 1, ncr), linspace(0, 1, ng), opt.gvar.ravel())
ind = np.flatnonzero(diff(cdf.args) > 0) # remove equal points
nd = len(ind)
ind1 = ind[Ne:nd - Ne]
tmp = invnorm(cdf.data[ind])
x = sigma * uu + mean
pp_tr = SmoothSpline(cdf.args[ind1], tmp[Ne:nd - Ne], p=opt.gsm, lin_extrap=opt.linextrap, var=gvar[ind1])
#g(:,2) = smooth(Fx(ind1,1),tmp(Ne+1:end-Ne),opt.gsm,g(:,1),def,gvar);
tr = TrData(pp_tr(x) , x, mean=mean, sigma=sigma)
tr_emp = TrData(tmp, cdf.args[ind], mean=mean, sigma=sigma)
tr_emp.setplotter('step')
if opt.chkder:
for ix in xrange(5):
dy = diff(tr.data)
if (dy <= 0).any():
dy[dy > 0] = floatinfo.eps
gvar = -(np.hstack((dy, 0)) + np.hstack((0, dy))) / 2 + floatinfo.eps
pp_tr = SmoothSpline(cdf.args[ind1], tmp[Ne:nd - Ne], p=1, lin_extrap=opt.linextrap, var=ix * gvar)
tr = TrData(pp_tr(x) , x, mean=mean, sigma=sigma)
else:
break
else:
msg = '''The empirical distribution is not sufficiently smoothed.
The estimated transfer function, g, is not
a strictly increasing function.'''
warnings.warn(msg)
g,g2 = the smoothed and empirical transformation, respectively.
A two column matrix if multip=0.
If multip=1 it is a 2*(m-1) column matrix where the
first and second column is the transform
for values in column 2 and third and fourth column is the
transform for values in column 3 ......
if opt.plotflag > 0:
tr.plot()
tr_emp.plot()
return tr, tr_emp
test = int (g(u)-u)^2 du where int. limits is given by param. This
is a measure of departure of the data from the Gaussian model.
def trdata(self, method='nonlinear', **options):
'''
Estimate transformation, g, from data.
Parameters
----------
method : string
'nonlinear' : transform based on smoothed crossing intensity (default)
'mnonlinear': transform based on smoothed marginal distribution
@ -1075,7 +1144,7 @@ class TimeSeries(WafoData):
'ochi' : transform based on exponential function
'linear' : identity.
options = options structure with the following fields:
options : keyword with the following fields:
csm,gsm - defines the smoothing of the logarithm of crossing intensity
and the transformation g, respectively. Valid values must
be 0<=csm,gsm<=1. (default csm=0.9, gsm=0.05)
@ -1101,10 +1170,14 @@ class TimeSeries(WafoData):
estimation for long time series without loosing any
accuracy. NTR should be chosen greater than
PARAM(3). (default 1000)
multip - 0 the data in columns belong to the same seastate (default).
1 the data in columns are from separate seastates.
DAT2TR estimates the transformation in a transformed Gaussian model.
Returns
-------
tr, tr_emp : TrData objects
with the smoothed and empirical transformation, respectively.
TRDATA estimates the transformation in a transformed Gaussian model.
Assumption: a Gaussian process, Y, is related to the
non-Gaussian process, X, by Y = g(X).
@ -1130,19 +1203,19 @@ class TimeSeries(WafoData):
>>> S.tr = tm.TrOchi(mean=0, skew=0.16, kurt=0, sigma=Hs/4, ysigma=Hs/4)
>>> xs = S.sim(ns=2**16, iseed=10)
>>> ts = mat2timeseries(xs)
>>> g0, gemp = ts.trdata(monitor=True) # Monitor the development
>>> g1, gemp = ts.trdata(method='m', gvar=0.5 ) # Equal weight on all points
>>> g2, gemp = ts.trdata(method='n', gvar=[3.5, 0.5, 3.5]) # Less weight on the ends
>>> g0, g0emp = ts.trdata(monitor=True) # Monitor the development
>>> g1, g1emp = ts.trdata(method='m', gvar=0.5 ) # Equal weight on all points
>>> g2, g2emp = ts.trdata(method='n', gvar=[3.5, 0.5, 3.5]) # Less weight on the ends
>>> int(S.tr.dist2gauss()*100)
593
>>> int(gemp.dist2gauss()*100)
431
>>> int(g0emp.dist2gauss()*100)
439
>>> int(g0.dist2gauss()*100)
342
432
>>> int(g1.dist2gauss()*100)
4.0
234
>>> int(g2.dist2gauss()*100)
342
437
Hm0 = 7;
S = jonswap([],Hm0); g=ochitr([],[Hm0/4]);
@ -1177,7 +1250,7 @@ class TimeSeries(WafoData):
# 'param',[-5 5 513],'delay',2,'linextrap','on','ne',7,...
# 'cvar',1,'gvar',1,'multip',0);
opt = DotDict(chkder=True, plotflag=True, csm=.95, gsm=.05,
opt = DotDict(chkder=True, plotflag=False, csm=.95, gsm=.05,
param=[-5, 5, 513], delay=2, ntr=inf, linextrap=True, ne=7, cvar=1, gvar=1,
multip=False, crossdef='uM')
opt.update(**options)
@ -1192,9 +1265,9 @@ class TimeSeries(WafoData):
tp = self.turning_points()
mM = tp.cycle_pairs()
lc = mM.level_crossings(opt.crossdef)
return lc.trdata()
return lc.trdata(mean=ma, sigma=sa, **opt)
elif method[0] == 'm':
return self._cdftr()
return self._trdata_cdf(**opt)
elif method[0] == 'h':
ga1 = skew(self.data)
ga2 = kurtosis(self.data, fisher=True) #kurt(xx(n+1:end))-3;
@ -1253,7 +1326,9 @@ class TimeSeries(WafoData):
t = self.args[ind]
except:
t = ind
return TurningPoints(self.data[ind], t)
mean = self.data.mean()
stdev = self.data.std()
return TurningPoints(self.data[ind], t, mean=mean, stdev=stdev)
def trough_crest(self, v=None, wavetype=None):
"""

@ -55,8 +55,6 @@ def edf(x, method=2):
See also edf, pdfplot, cumtrapz
'''
z = atleast_1d(x)
z.sort()

Loading…
Cancel
Save