You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1896 lines
55 KiB
Python

'''
Misc lsdkfalsdflasdfl
'''
from __future__ import division
import sys
import numpy as np
from numpy import abs
from numpy import amax
from numpy import any
from numpy import arange
from numpy import arctan2
from numpy import array
from numpy import asarray
from numpy import atleast_1d
from numpy import broadcast_arrays
from numpy import ceil
from numpy import cos
from numpy import diff
from numpy import empty_like
from numpy import exp
from numpy import extract
from numpy import finfo
from numpy import floor
from numpy import frexp
from numpy import hstack
from numpy import hypot
from numpy import inf
from numpy import interp
from numpy import isnan
from numpy import isscalar
from numpy import linspace
from numpy import log
from numpy import logical_and
from numpy import mod
from numpy import nonzero
from numpy import ones
from numpy import pi
from numpy import r_
from numpy import sign
from numpy import sin
from numpy import sqrt
from numpy import unique1d
from numpy import vstack
from numpy import where
from numpy import zeros
from scipy.special import gammaln
import types
import warnings
try:
import wafo.c_library as clib
except:
clib = None
floatinfo = finfo(float)
__all__ = ['JITImport', 'DotDict', 'Bunch', 'printf', 'sub_dict_select',
'parse_kwargs', 'ecross', 'findtc', 'findtp', 'findcross',
'findextrema', 'findrfc', 'rfcfilter', 'common_shape', 'argsreduce',
'stirlerr', 'getshipchar', 'betaloge', 'gravity', 'nextpow2',
'discretize', 'pol2cart', 'cart2pol', 'ndgrid', 'meshgrid']
class JITImport(object):
'''
Just In Time Import of module
Example
-------
>>> np = JITImport('numpy')
>>> np.exp(0)==1.0
True
'''
def __init__(self, module_name):
self._module_name = module_name
self._module = None
def __getattr__(self, attr):
try:
return getattr(self._module, attr)
except:
if self._module is None:
self._module = __import__(self._module_name, None, None, ['*'])
assert(isinstance(self._module, types.ModuleType), 'module')
return getattr(self._module, attr)
else:
raise
class DotDict(dict):
''' Implement dot access to dict values
Example
-------
>>> d = DotDict(test1=1,test2=3)
>>> d.test1
1
'''
__getattr__ = dict.__getitem__
class Bunch(object):
''' Implement keyword argument initialization of class
'''
def __init__(self, ** kwargs):
self.__dict__.update(kwargs)
def keys(self):
return self.__dict__.keys()
def update(self, ** kwargs):
self.__dict__.update(kwargs)
def printf(format, * args):
sys.stdout.write(format % args)
def sub_dict_select(somedict, somekeys):
'''
Extracting a Subset from Dictionary
Example
--------
# Update options dict from keyword arguments if
# the keyword exists in options
>>> opt = dict(arg1=2, arg2=3)
>>> kwds = dict(arg2=100,arg3=1000)
>>> sub_dict = sub_dict_select(kwds,opt.keys())
>>> opt.update(sub_dict)
>>> opt
{'arg1': 2, 'arg2': 100}
See also
--------
dict_intersection
'''
#slower: validKeys = set(somedict).intersection(somekeys)
return dict((k, somedict[k]) for k in somekeys if k in somedict)
def parse_kwargs(options, ** kwargs):
''' Update options dict from keyword arguments if the keyword exists in options
Example
>>> opt = dict(arg1=2, arg2=3)
>>> opt = parse_kwargs(opt,arg2=100)
>>> print opt
{'arg1': 2, 'arg2': 100}
>>> opt2 = dict(arg2=101)
>>> opt = parse_kwargs(opt,**opt2)
See also sub_dict_select
'''
newopts = sub_dict_select(kwargs, options.keys())
if len(newopts) > 0:
options.update(newopts)
return options
def testfun(*args, ** kwargs):
opts = dict(opt1=1, opt2=2)
if len(args) == 1 and len(kwargs) == 0 and type(args[0]) is str and args[0].startswith('default'):
return opts
opts = parse_kwargs(opts, ** kwargs)
return opts
def detrendma(x, L):
"""
Removes a trend from data using a moving average
of size 2*L+1. If 2*L+1 > len(x) then the mean is removed
Parameters
----------
x : vector or matrix of column vectors
of data
L : scalar, integer
defines the size of the moving average window
Returns
-------
y : ndarray
detrended data
Examples
--------
>>> import pylab as plb
>>> exp = plb.exp; cos = plb.cos; randn = plb.randn
>>> x = plb.linspace(0,1,200)
>>> y = exp(x)+cos(5*2*pi*x)+1e-1*randn(x.size)
>>> y0 = detrendma(y,20); tr = y-y0
>>> h = plb.plot(x, y, x, y0, 'r', x, exp(x), 'k', x, tr, 'm')
>>> plb.close('all')
See also
--------
Reconstruct
"""
if L <= 0:
raise ValueError('L must be positive')
if L != round(L):
raise ValueError('L must be an integer')
x1 = atleast_1d(x)
if x1.shape[0] == 1:
x1 = x1.ravel()
n = x1.shape[0]
if n < 2 * L + 1: # only able to remove the mean
return x1 - x1.mean(axis=0)
mn = x1[0:2 * L + 1].mean(axis=0)
y = empty_like(x1)
y[0:L] = x1[0:L] - mn
ix = r_[L:(n - L)]
trend = ((x1[ix + L] - x1[ix - L]) / (2 * L + 1)).cumsum(axis=0) + mn
y[ix] = x1[ix] - trend
y[n - L::] = x1[n - L::] - trend[-1]
return y
def ecross(t, f, ind, v):
'''
Extracts exact level v crossings
ECROSS interpolates t and f linearly to find the exact level v
crossings, i.e., the points where f(t0) = v
Parameters
----------
t,f : vectors
of arguments and functions values, respectively.
ind : ndarray of integers
indices to level v crossings as found by findcross.
v : scalar or vector (of size(ind))
defining the level(s) to cross.
Returns
-------
t0 : vector
of exact level v crossings.
Example
-------
>>> from matplotlib import pylab as plb
>>> ones = plb.ones
>>> t = plb.linspace(0,7*plb.pi,250)
>>> x = plb.sin(t)
>>> ind = findcross(x,0.75)
>>> ind
array([ 9, 25, 80, 97, 151, 168, 223, 239])
>>> t0 = ecross(t,x,ind,0.75)
>>> t0
array([ 0.84910514, 2.2933879 , 7.13205663, 8.57630119,
13.41484739, 14.85909194, 19.69776067, 21.14204343])
>>> a = plb.plot(t, x, '.', t[ind], x[ind], 'r.', t, ones(t.shape)*0.75,
... t0, ones(t0.shape)*0.75, 'g.')
>>> plb.close('all')
See also
--------
findcross
'''
return t[ind] + (v - f[ind]) * (t[ind + 1] - t[ind]) / (f[ind + 1] - f[ind])
def _findcross(xn):
'''Return indices to zero up and downcrossings of a vector
'''
if clib is not None:
ind, m = clib.findcross(xn, 0.0)
return ind[:m]
n = len(xn)
iz, = (xn == 0).nonzero()
if any(iz):
# Trick to avoid turning points on the crossinglevel.
if iz[0] == 0:
if len(iz) == n:
warnings.warn('All values are equal to crossing level!')
return zeros(0, dtype=np.int)
diz = diff(iz)
ix = iz((diz > 1).argmax())
if not any(ix):
ix = iz[-1]
#x(ix) is a up crossing if x(1:ix) = v and x(ix+1) > v.
#x(ix) is a downcrossing if x(1:ix) = v and x(ix+1) < v.
xn[0:ix] = -xn[ix + 1]
iz = iz[ix::]
for ix in iz.tolist():
xn[ix] = xn[ix - 1]
#% indices to local level crossings ( without turningpoints)
ind, = (xn[:n - 1] * xn[1:] < 0).nonzero()
return ind
def findcross(x, v=0.0, kind=None):
'''
Return indices to level v up and/or downcrossings of a vector
Parameters
----------
x : array_like
vector with sampled values.
v : scalar, real
level v.
kind : string
defines type of wave or crossing returned. Possible options are
'dw' : downcrossing wave
'uw' : upcrossing wave
'cw' : crest wave
'tw' : trough wave
'd' : downcrossings only
'u' : upcrossings only
None : All crossings will be returned
Returns
-------
ind : array-like
indices to the crossings in the original sequence x.
Example
-------
>>> from matplotlib import pylab as plb
>>> ones = plb.ones
>>> v = 0.75
>>> t = plb.linspace(0,7*plb.pi,250)
>>> x = plb.sin(t)
>>> ind = findcross(x,v) # all crossings
>>> ind
array([ 9, 25, 80, 97, 151, 168, 223, 239])
>>> t0 = plb.plot(t,x,'.',t[ind],x[ind],'r.', t, ones(t.shape)*v)
>>> ind2 = findcross(x,v,'u')
>>> ind2
array([ 9, 80, 151, 223])
>>> t0 = plb.plot(t[ind2],x[ind2],'o')
>>> plb.close('all')
See also
--------
crossdef
wavedef
'''
xn = np.int8(sign(atleast_1d(x).ravel() - v)) #@UndefinedVariable
ind = _findcross(xn)
if ind.size == 0:
warnings.warn('No level v = %0.5g crossings found in x' % v)
return ind
if kind not in ('du', 'all', None):
if kind == 'd': #downcrossings only
t_0 = int(xn[ind[0] + 1] > 0)
ind = ind[t_0::2]
elif kind == 'u': #upcrossings only
t_0 = int(xn[ind[0] + 1] < 0)
ind = ind[t_0::2]
elif kind in ('dw', 'uw', 'tw', 'cw'):
#make sure that the first is a level v down-crossing if wdef=='dw'
#or make sure that the first is a level v up-crossing if wdef=='uw'
#make sure that the first is a level v down-crossing if wdef=='tw'
#or make sure that the first is a level v up-crossing if wdef=='cw'
xor = lambda a, b: a ^ b
first_is_down_crossing = int(xn[ind[0]] > xn[ind[0] + 1])
if xor(first_is_down_crossing, kind in ('dw', 'tw')):
ind = ind[1::]
n_c = ind.size # number of level v crossings
# make sure the number of troughs and crests are according to the
# wavedef, i.e., make sure length(ind) is odd if dw or uw
# and even if tw or cw
is_odd = mod(n_c, 2)
if xor(is_odd, kind in ('dw', 'uw')):
ind = ind[:-1]
else:
raise ValueError('Unknown wave/crossing definition!')
return ind
def findextrema(x):
'''
Return indices to minima and maxima of a vector
Parameters
----------
x : vector with sampled values.
Returns
-------
ind : indices to minima and maxima in the original sequence x.
Examples
--------
>>> import numpy as np
>>> import pylab as pb
>>> t = np.linspace(0,7*np.pi,250)
>>> x = np.sin(t)
>>> ind = findextrema(x)
>>> a = pb.plot(t,x,'.',t[ind],x[ind],'r.')
>>> pb.close('all')
See also
--------
findcross
crossdef
'''
xn = atleast_1d(x).ravel()
return findcross(diff(xn), 0.0) + 1
def findrfc(tp, hmin=0.0):
'''
Return indices to rainflow cycles of a sequence of TP.
Parameters
-----------
tp : array-like
vector of turningpoints (NB! Only values, not sampled times)
h : real scalar
rainflow threshold. If h>0, then all rainflow cycles with height
smaller than h are removed.
Returns
-------
ind : ndarray of int
indices to the rainflow cycles of the original sequence TP.
Example:
--------
>>> import pylab as pb
>>> t = pb.linspace(0,7*np.pi,250)
>>> x = pb.sin(t)+0.1*np.sin(50*t)
>>> ind = findextrema(x)
>>> ti, tp = t[ind], x[ind]
>>> a = pb.plot(t,x,'.',ti,tp,'r.')
>>> ind1 = findrfc(tp,0.3)
>>> a = pb.plot(ti[ind1],tp[ind1])
>>> pb.close('all')
See also
--------
rfcfilter,
findtp.
'''
# TODO merge rfcfilter and findrfc
y1 = atleast_1d(tp).ravel()
n = len(y1)
ind = zeros(0, dtype=np.int)
ix = 0
if y1[0] > y1[1]:
#first is a max, ignore it
y = y1[1::]
NC = floor((n - 1) / 2) - 1
Tstart = 1
else:
y = y1
NC = floor(n / 2) - 1
Tstart = 0
if (NC < 1):
return ind #No RFC cycles*/
if (y[0] > y[1]) and (y[1] > y[2]):
warnings.warn('This is not a sequence of turningpoints, exit')
return ind
if (y[0] < y[1]) and (y[1] < y[2]):
warnings.warn('This is not a sequence of turningpoints, exit')
return ind
if clib is None:
ind = zeros(n, dtype=np.int)
NC = np.int(NC)
for i in xrange(NC):
Tmi = Tstart + 2 * i
Tpl = Tstart + 2 * i + 2
xminus = y[2 * i]
xplus = y[2 * i + 2]
if(i != 0):
j = i - 1
while ((j >= 0) and (y[2 * j + 1] <= y[2 * i + 1])):
if (y[2 * j] < xminus):
xminus = y[2 * j]
Tmi = Tstart + 2 * j
j -= 1
if (xminus >= xplus):
if (y[2 * i + 1] - xminus >= hmin):
ind[ix] = Tmi
ix += 1
ind[ix] = (Tstart + 2 * i + 1)
ix += 1
#goto L180 continue
else:
j = i + 1
while (j < NC):
if (y[2 * j + 1] >= y[2 * i + 1]):
break #goto L170
if((y[2 * j + 2] <= xplus)):
xplus = y[2 * j + 2]
Tpl = (Tstart + 2 * j + 2)
j += 1
else:
if ((y[2 * i + 1] - xminus) >= hmin):
ind[ix] = Tmi
ix += 1
ind[ix] = (Tstart + 2 * i + 1)
ix += 1
#iy = i
continue
#goto L180
#L170:
if (xplus <= xminus):
if ((y[2 * i + 1] - xminus) >= hmin):
ind[ix] = Tmi
ix += 1
ind[ix] = (Tstart + 2 * i + 1)
ix += 1
elif ((y[2 * i + 1] - xplus) >= hmin):
ind[ix] = (Tstart + 2 * i + 1)
ix += 1
ind[ix] = Tpl
ix += 1
#L180:
#iy=i
# /* for i */
else:
ind, ix = clib.findrfc(y, hmin)
return ind[:ix]
def rfcfilter(x, h, method=0):
"""
Rainflow filter a signal.
Parameters
-----------
x : vector
Signal. [nx1]
h : real, scalar
Threshold for rainflow filter.
method : scalar, integer
0 : removes cycles with range < h. (default)
1 : removes cycles with range <= h.
Returns
--------
y = Rainflow filtered signal.
Examples:
---------
# 1. Filtered signal y is the turning points of x.
>>> import wafo.data
>>> x = wafo.data.sea()
>>> y = rfcfilter(x[:,1], h=0, method=1)
>>> y[0:5]
array([-1.2004945 , 0.83950546, -0.09049454, -0.02049454, -0.09049454])
# 2. This removes all rainflow cycles with range less than 0.5.
>>> y1 = rfcfilter(x[:,1], h=0.5)
>>> y1[0:5]
array([-1.2004945 , 0.83950546, -0.43049454, 0.34950546, -0.51049454])
See also
--------
findrfc
"""
# TODO merge rfcfilter and findrfc
y = atleast_1d(x).ravel()
n = len(y)
t = zeros(n, dtype=np.int)
j = 0
t0 = 0
y0 = y[t0]
z0 = 0
if method == 0:
cmpfun1 = lambda a, b: a <= b
cmpfun2 = lambda a, b: a < b
else:
cmpfun1 = lambda a, b: a < b
cmpfun2 = lambda a, b: a <= b
#% The rainflow filter
for tim1, yi in enumerate(y[1::]):
fpi = y0 + h
fmi = y0 - h
ti = tim1 + 1
#yi = y[ti]
if z0 == 0:
if cmpfun1(yi, fmi):
z1 = -1
elif cmpfun1(fpi, yi):
z1 = + 1
else:
z1 = 0
t1, y1 = (t0, y0) if z1 == 0 else (ti, yi)
else:
if (((z0 == + 1) & cmpfun1(yi, fmi)) | ((z0 == -1) & cmpfun2(yi, fpi))):
z1 = -1
elif (((z0 == + 1) & cmpfun2(fmi, yi)) | ((z0 == -1) & cmpfun1(fpi, yi))):
z1 = + 1
else:
warnings.warn('Something wrong, i=%d' % tim1)
#% Update y1
if z1 != z0:
t1, y1 = ti, yi
elif z1 == -1:
#% y1 = min([y0 xi])
t1, y1 = (t0, y0) if y0 < yi else (ti, yi)
elif z1 == + 1:
#% y1 = max([y0 xi])
t1, y1 = (t0, y0) if y0 > yi else (ti, yi)
#% Update y if y0 is a turning point
if abs(z0 - z1) == 2:
j += 1
t[j] = t0
#% Update t0, y0, z0
t0, y0, z0 = t1, y1, z1
#end
#% Update y if last y0 is greater than (or equal) threshold
if cmpfun1(h, abs(y0 - y[t[j]])):
j += 1
t[j] = t0
return y[t[:j]]
def findtp(x, h=0.0, kind=None):
'''
Return indices to turning points (tp) of data, optionally rainflowfiltered.
Parameters
----------
x : vector
signal
h : real, scalar
rainflow threshold
if h<0, then ind = range(len(x))
if h=0, then tp is a sequence of turning points (default)
if h>0, then all rainflow cycles with height smaller than
h are removed.
kind : string
defines the type of wave. Possible options are
'mw' 'Mw' or 'none'.
If None all rainflow filtered min and max
will be returned, otherwise only the rainflow filtered
min and max, which define a wave according to the
wave definition, will be returned.
Returns
-------
ind : arraylike
indices to the turning points in the original sequence.
Example:
--------
>>> import wafo.data
>>> import pylab
>>> x = wafo.data.sea()
>>> x1 = x[0:200,:]
>>> itp = findtp(x1[:,1],0,'Mw')
>>> itph = findtp(x1[:,1],0.3,'Mw')
>>> tp = x1[itp,:]
>>> tph = x1[itph,:]
>>> a = pylab.plot(x1[:,0],x1[:,1],tp[:,0],tp[:,1],'ro',tph[:,1],tph[:,1],'k.')
>>> pylab.close('all')
See also
---------
findtc
findcross
findextrema
findrfc
'''
n = len(x)
if h < 0.0:
return arange(n)
ind = findextrema(x)
if ind.size < 2:
return None
#% In order to get the exact up-crossing intensity from rfc by
#% mm2lc(tp2mm(rfc)) we have to add the indices
#% to the last value (and also the first if the
#% sequence of turning points does not start with a minimum).
if x[ind[0]] > x[ind[1]]:
#% adds indices to first and last value
ind = r_[0, ind, n - 1]
else: # adds index to the last value
ind = r_[ind, n - 1]
if h > 0.0:
ind1 = findrfc(x[ind], h)
ind = ind[ind1]
if kind in ('mw', 'Mw'):
xor = lambda a, b: a ^ b
# make sure that the first is a Max if wdef == 'Mw'
# or make sure that the first is a min if wdef == 'mw'
first_is_max = (x[ind[0]] > x[ind[1]])
remove_first = xor(first_is_max, kind.startswith('Mw'))
if remove_first:
ind = ind[1::]
# make sure the number of minima and Maxima are according to the wavedef.
# i.e., make sure Nm=length(ind) is odd
if (mod(ind.size, 2)) != 1:
ind = ind[:-1]
return ind
def findtc(x_in, v=None, kind=None):
"""
Return indices to troughs and crests of data.
Parameters
----------
x : vector
surface elevation.
v : real scalar
reference level (default v = mean of x).
kind : string
defines the type of wave. Possible options are
'dw', 'uw', 'tw', 'cw' or None.
If None indices to all troughs and crests will be returned,
otherwise only the paired ones will be returned
according to the wavedefinition.
Returns
--------
tc_ind : vector of ints
indices to the trough and crest turningpoints of sequence x.
v_ind : vector of ints
indices to the level v crossings of the original
sequence x. (d,u)
Example:
--------
>>> import wafo.data
>>> import pylab
>>> x = wafo.data.sea()
>>> x1 = x[0:200,:]
>>> itc, iv = findtc(x1[:,1],0,'dw')
>>> tc = x1[itc,:]
>>> a = pylab.plot(x1[:,0],x1[:,1],tc[:,0],tc[:,1],'ro')
>>> pylab.close('all')
See also
--------
findtp
findcross,
wavedef
"""
x = atleast_1d(x_in)
if v is None:
v = x.mean()
v_ind = findcross(x, v, kind)
n_c = v_ind.size
if n_c <= 2:
warnings.warn('There are no waves!')
return zeros(0, dtype=np.int), zeros(0, dtype=np.int)
# determine the number of trough2crest (or crest2trough) cycles
isodd = mod(n_c, 2)
if isodd:
n_tc = int((n_c - 1) / 2)
else:
n_tc = int((n_c - 2) / 2)
#% allocate variables before the loop increases the speed
ind = zeros(n_c - 1, dtype=np.int)
first_is_down_crossing = (x[v_ind[0]] > x[v_ind[0] + 1])
if first_is_down_crossing:
for i in xrange(n_tc):
#% trough
j = 2 * i
ind[j] = x[v_ind[j] + 1:v_ind[j + 1] + 1].argmin()
#% crest
ind[j + 1] = x[v_ind[j + 1] + 1:v_ind[j + 2] + 1].argmax()
if (2 * n_tc + 1 < n_c) and (kind in (None, 'tw')):
#% trough
ind[n_c - 2] = x[v_ind[n_c - 2] + 1:v_ind[n_c - 1]].argmin()
else: # %%%% the first is a up-crossing
for i in xrange(n_tc):
#% trough
j = 2 * i
ind[j] = x[v_ind[j] + 1:v_ind[j + 1] + 1].argmax()
#% crest
ind[j + 1] = x[v_ind[j + 1] + 1:v_ind[j + 2] + 1].argmin()
if (2 * n_tc + 1 < n_c) and (kind in (None, 'cw')):
#% trough
ind[n_c - 2] = x[v_ind[n_c - 2] + 1:v_ind[n_c - 1]].argmax()
return v_ind[:n_c - 1] + ind + 1, v_ind
def findoutliers(x, zcrit=0.0, dcrit=None, ddcrit=None, verbose=False):
"""
Return indices to spurious points of data
Parameters
----------
x : vector
of data values.
zcrit : real scalar
critical distance between consecutive points.
dcrit : real scalar
critical distance of Dx used for determination of spurious
points. (Default 1.5 standard deviation of x)
ddcrit : real scalar
critical distance of DDx used for determination of spurious
points. (Default 1.5 standard deviation of x)
Returns
-------
inds : ndarray of integers
indices to spurious points.
indg : ndarray of integers
indices to the rest of the points.
Notes
-----
Consecutive points less than zcrit apart are considered as spurious.
The point immediately after and before are also removed. Jumps greater than
dcrit in Dxn and greater than ddcrit in D^2xn are also considered as spurious.
(All distances to be interpreted in the vertical direction.)
Another good choice for dcrit and ddcrit are:
dcrit = 5*dT and ddcrit = 9.81/2*dT**2
where dT is the timestep between points.
Examples
--------
>>> import numpy as np
>>> import wafo
>>> xx = wafo.data.sea()
>>> dt = np.diff(xx[:2,0])
>>> dcrit = 5*dt
>>> ddcrit = 9.81/2*dt*dt
>>> zcrit = 0
>>> [inds, indg] = findoutliers(xx[:,1],zcrit,dcrit,ddcrit,verbose=True)
Found 0 spurious positive jumps of Dx
Found 0 spurious negative jumps of Dx
Found 37 spurious positive jumps of D^2x
Found 200 spurious negative jumps of D^2x
Found 244 consecutive equal values
Found the total of 1152 spurious points
#waveplot(xx,'-',xx(inds,:),1,1,1)
See also
--------
waveplot, reconstruct
"""
# finding outliers
findjumpsDx = True # find jumps in Dx
# two point spikes and Spikes dcrit above/under the
# previous and the following point are spurios.
findSpikes = False #find spikes
findDspikes = False # find double (two point) spikes
findjumpsD2x = True # find jumps in D^2x
findNaN = True # % find missing values
xn = asarray(x).flatten()
if xn.size < 2:
raise ValueError('The vector must have more than 2 elements!')
ind = zeros(0, dtype=int)
#indg=[]
indmiss = isnan(xn)
if findNaN and indmiss.any():
ind, = nonzero(indmiss)
if verbose:
print('Found %d missing points' % ind.size)
xn[indmiss] = 0. #%set NaN's to zero
if dcrit is None:
dcrit = 1.5 * xn.std()
if verbose:
print('dcrit is set to %g' % dcrit)
if ddcrit is None:
ddcrit = 1.5 * xn.std()
if verbose:
print('ddcrit is set to %g' % ddcrit)
dxn = diff(xn)
ddxn = diff(dxn)
if findSpikes: # finding spurious spikes
tmp, = nonzero((dxn[:-1] > dcrit) * (dxn[1::] < -dcrit) |
(dxn[:-1] < -dcrit) * (dxn[1::] > dcrit))
if tmp.size > 0:
tmp = tmp + 1
ind = hstack((ind, tmp))
if verbose:
print('Found %d spurious spikes' % tmp.size)
if findDspikes: #,% finding spurious double (two point) spikes
tmp, = nonzero((dxn[:-2] > dcrit) * (dxn[2::] < -dcrit) |
(dxn[:-2] < -dcrit) * (dxn[2::] > dcrit))
if tmp.size > 0:
tmp = tmp + 1
ind = hstack((ind, tmp, tmp + 1)) #%removing both points
if verbose:
print('Found %d spurious two point (double) spikes' % tmp.size)
if findjumpsDx: # ,% finding spurious jumps in Dx
tmp, = nonzero(dxn > dcrit)
if verbose:
print('Found %d spurious positive jumps of Dx' % tmp.size)
if tmp.size > 0:
ind = hstack((ind, tmp + 1)) #removing the point after the jump
tmp, = nonzero(dxn < -dcrit)
if verbose:
print('Found %d spurious negative jumps of Dx' % tmp.size)
if tmp.size > 0:
ind = hstack((ind, tmp)) #removing the point before the jump
if findjumpsD2x: # ,% finding spurious jumps in D^2x
tmp, = nonzero(ddxn > ddcrit)
if tmp.size > 0:
tmp = tmp + 1
ind = hstack((ind, tmp)) # removing the jump
if verbose:
print('Found %d spurious positive jumps of D^2x' % tmp.size)
tmp, = nonzero(ddxn < -ddcrit)
if tmp.size > 0:
tmp = tmp + 1
ind = hstack((ind, tmp)) # removing the jump
if verbose:
print('Found %d spurious negative jumps of D^2x' % tmp.size)
if zcrit >= 0.0:
#% finding consecutive values less than zcrit apart.
indzeros = (abs(dxn) <= zcrit)
indz, = nonzero(indzeros)
if indz.size > 0:
indz = indz + 1
#%finding the beginning and end of consecutive equal values
indtr, = nonzero((diff(indzeros)))
indtr = indtr + 1
#%indices to consecutive equal points
if True: # removing the point before + all equal points + the point after
ind = hstack((ind, indtr - 1, indz, indtr, indtr + 1))
else: # % removing all points + the point after
ind = hstack((ind, indz, indtr, indtr + 1))
if verbose:
if zcrit == 0.:
print('Found %d consecutive equal values' % indz.size)
else:
print('Found %d consecutive values less than %g apart.' % (indz.size, zcrit))
indg = ones(xn.size, dtype=bool)
if ind.size > 1:
ind = unique1d(ind)
indg[ind] = 0
indg, = nonzero(indg)
if verbose:
print('Found the total of %d spurious points' % ind.size)
return ind, indg
def common_shape(*args, ** kwds):
'''
Return the common shape of a sequence of arrays
Parameters
-----------
*args : arraylike
sequence of arrays
**kwds :
shape
Returns
-------
shape : tuple
common shape of the elements of args.
Raises
------
An error is raised if some of the arrays do not conform
to the common shape according to the broadcasting rules in numpy.
Examples
--------
>>> import numpy as np
>>> A = np.ones((4,1))
>>> B = 2
>>> C = np.ones((1,5))*5
>>> common_shape(A,B,C)
(4, 5)
>>> common_shape(A,B,C,shape=(3,4,1))
(3, 4, 5)
See also
--------
broadcast, broadcast_arrays
'''
args = map(asarray, args)
shapes = [x.shape for x in args]
shape = kwds.get('shape')
if shape is not None:
if not isinstance(shape, (list, tuple)):
shape = (shape, )
shapes.append(tuple(shape))
if len(set(shapes)) == 1:
# Common case where nothing needs to be broadcasted.
return tuple(shapes[0])
shapes = [list(s) for s in shapes]
nds = [len(s) for s in shapes]
biggest = max(nds)
# Go through each array and prepend dimensions of length 1 to each of the
# shapes in order to make the number of dimensions equal.
for i in range(len(shapes)):
diff = biggest - nds[i]
if diff > 0:
shapes[i] = [1] * diff + shapes[i]
# Check each dimension for compatibility. A dimension length of 1 is
# accepted as compatible with any other length.
c_shape = []
for axis in range(biggest):
lengths = [s[axis] for s in shapes]
unique = set(lengths + [1])
if len(unique) > 2:
# There must be at least two non-1 lengths for this axis.
raise ValueError("shape mismatch: two or more arrays have "
"incompatible dimensions on axis %r." % (axis, ))
elif len(unique) == 2:
# There is exactly one non-1 length. The common shape will take this
# value.
unique.remove(1)
new_length = unique.pop()
c_shape.append(new_length)
else:
# Every array has a length of 1 on this axis. Strides can be left
# alone as nothing is broadcasted.
c_shape.append(1)
return tuple(c_shape)
def argsreduce(condition, * args):
""" Return the elements of each input array that satisfy some condition.
Parameters
----------
condition : array_like
An array whose nonzero or True entries indicate the elements of each
input array to extract. The shape of 'condition' must match the common
shape of the input arrays according to the broadcasting rules in numpy.
arg1, arg2, arg3, ... : array_like
one or more input arrays.
Returns
-------
narg1, narg2, narg3, ... : ndarray
sequence of extracted copies of the input arrays converted to the same
size as the nonzero values of condition.
Example
-------
>>> import numpy as np
>>> rand = np.random.random_sample
>>> A = rand((4,5))
>>> B = 2
>>> C = rand((1,5))
>>> cond = np.ones(A.shape)
>>> [A1,B1,C1] = argsreduce(cond,A,B,C)
>>> B1.shape
(20,)
>>> cond[2,:] = 0
>>> [A2,B2,C2] = argsreduce(cond,A,B,C)
>>> B2.shape
(15,)
See also
--------
numpy.extract
"""
newargs = atleast_1d(*args)
if not isinstance(newargs, list):
newargs = [newargs,]
expand_arr = (condition == condition)
return [extract(condition, arr1 * expand_arr) for arr1 in newargs]
def stirlerr(n):
'''
Return error of Stirling approximation, i.e., log(n!) - log( sqrt(2*pi*n)*(n/exp(1))**n )
Example
-------
>>> stirlerr(2)
array([ 0.0413407])
See also
---------
binom
Reference
-----------
Catherine Loader (2000).
Fast and Accurate Computation of Binomial Probabilities
<http://www.herine.net/stat/software/dbinom.html>
<http://www.citeseer.ist.psu.edu/312695.html>
'''
S0 = 0.083333333333333333333 # /* 1/12 */
S1 = 0.00277777777777777777778 # /* 1/360 */
S2 = 0.00079365079365079365079365 # /* 1/1260 */
S3 = 0.000595238095238095238095238 # /* 1/1680 */
S4 = 0.0008417508417508417508417508 # /* 1/1188 */
n1 = atleast_1d(n)
y = gammaln(n1 + 1) - log(sqrt(2 * pi * n1) * (n1 / exp(1)) ** n1)
nn = n1 * n1
n500 = 500 < n1
y[n500] = (S0 - S1 / nn[n500]) / n1[n500]
n80 = logical_and(80 < n1, n1 <= 500)
if any(n80):
y[n80] = (S0 - (S1 - S2 / nn[n80]) / nn[n80]) / n1[n80]
n35 = logical_and(35 < n1, n1 <= 80)
if any(n35):
nn35 = nn[n35]
y[n35] = (S0 - (S1 - (S2 - S3 / nn35) / nn35) / nn35) / n1[n35]
n15 = logical_and(15 < n1, n1 <= 35)
if any(n15):
nn15 = nn[n15]
y[n15] = (S0 - (S1 - (S2 - (S3 - S4 / nn15) / nn15) / nn15) / nn15) / n1[n15]
return y
def getshipchar(value, property="max_deadweight"):
'''
Return ship characteristics from value of one ship-property
Parameters
----------
value : scalar
value to use in the estimation.
property : string
defining the ship property used in the estimation. Options are:
'max_deadweight','length','beam','draft','service_speed',
'propeller_diameter'.
The length was found from statistics of 40 vessels of size 85 to
100000 tonn. An exponential curve through 0 was selected, and the
factor and exponent that minimized the standard deviation of the relative
error was selected. (The error returned is the same for any ship.) The
servicespeed was found for ships above 1000 tonns only.
The propeller diameter formula is from [1]_.
Returns
-------
sc : dict
containing estimated mean values and standard-deviations of ship characteristics:
max_deadweight [kkg], (weight of cargo, fuel etc.)
length [m]
beam [m]
draught [m]
service_speed [m/s]
propeller_diameter [m]
Example
---------
>>> getshipchar(10,'service_speed')
{'beam': 29.0,
'beamSTD': 2.9000000000000004,
'draught': 9.5999999999999996,
'draughtSTD': 2.1120000000000001,
'length': 216.0,
'lengthSTD': 2.0113098831942762,
'max_deadweight': 30969.0,
'max_deadweightSTD': 3096.9000000000001,
'propeller_diameter': 6.761165385916601,
'propeller_diameterSTD': 0.20267047566705432,
'service_speed': 10.0,
'service_speedSTD': 0}
Other units: 1 ft = 0.3048 m and 1 knot = 0.5144 m/s
Reference
---------
.. [1] Gray and Greeley, (1978),
"Source level model for propeller blade rate radiation for the world's merchant
fleet", Bolt Beranek and Newman Technical Memorandum No. 458.
'''
valid_props = dict(l='length', b='beam', d='draught', m='max_deadweigth',
s='service_speed', p='propeller_diameter')
prop = valid_props[property[0]]
prop2max_dw = dict(length=lambda x: (x / 3.45) ** (2.5),
beam=lambda x: ((x / 1.78) ** (1 / 0.27)),
draught=lambda x: ((x / 0.8) ** (1 / 0.24)),
service_speed=lambda x: ((x / 1.14) ** (1 / 0.21)),
propeller_diameter=lambda x: (((x / 0.12) ** (4 / 3) / 3.45) ** (2.5)))
max_deadweight = prop2max_dw.get(prop, lambda x: x)(value)
propertySTD = prop + 'STD'
length = round(3.45 * max_deadweight ** 0.40)
length_err = length ** 0.13
beam = round(1.78 * max_deadweight ** 0.27 * 10) / 10
beam_err = beam * 0.10
draught = round(0.80 * max_deadweight ** 0.24 * 10) / 10
draught_err = draught * 0.22
#S = round(2/3*(L)**0.525)
speed = round(1.14 * max_deadweight ** 0.21 * 10) / 10
speed_err = speed * 0.10
p_diam = 0.12 * length ** (3.0 / 4.0)
p_diam_err = 0.12 * length_err ** (3.0 / 4.0)
max_deadweight = round(max_deadweight)
max_deadweightSTD = 0.1 * max_deadweight
shipchar = {'max_deadweight':max_deadweight, 'max_deadweightSTD':max_deadweightSTD,
'length':length, 'lengthSTD':length_err, 'beam':beam, 'beamSTD':beam_err,
'draught':draught, 'draughtSTD':draught_err,
'service_speed':speed, 'service_speedSTD':speed_err,
'propeller_diameter':p_diam, 'propeller_diameterSTD':p_diam_err}
shipchar[propertySTD] = 0
return shipchar
def betaloge(z, w):
'''
Natural Logarithm of beta function.
CALL betaloge(z,w)
BETALOGE computes the natural logarithm of the beta
function for corresponding elements of Z and W. The arrays Z and
W must be real and nonnegative. Both arrays must be the same size,
or either can be scalar. BETALOGE is defined as:
y = LOG(BETA(Z,W)) = gammaln(Z)+gammaln(W)-gammaln(Z+W)
and is obtained without computing BETA(Z,W). Since the beta
function can range over very large or very small values, its
logarithm is sometimes more useful.
This implementation is more accurate than the BETALN implementation
for large arguments
Example
See also
--------
betaln, beta
'''
# y = gammaln(z)+gammaln(w)-gammaln(z+w)
zpw = z + w
return (stirlerr(z) + stirlerr(w) + 0.5 * log(2 * pi) + (w - 0.5) * log(w)
+ (z - 0.5) * log(z) - stirlerr(zpw) - (zpw - 0.5) * log(zpw))
# stirlings approximation:
# (-(zpw-0.5).*log(zpw) +(w-0.5).*log(w)+(z-0.5).*log(z) +0.5*log(2*pi))
#return y
def gravity(phi=45):
''' Returns the constant acceleration of gravity
GRAVITY calculates the acceleration of gravity
using the international gravitational formulae [1]_:
g = 9.78049*(1+0.0052884*sin(phir)**2-0.0000059*sin(2*phir)**2)
where
phir = phi*pi/180
Parameters
----------
phi : {float, int}
latitude in degrees
Returns
--------
g : ndarray
acceleration of gravity [m/s**2]
Examples
--------
>>> import numpy as np
>>> phi = np.linspace(0,45,5)
>>> gravity(phi)
array([ 9.78049 , 9.78245014, 9.78803583, 9.79640552, 9.80629387])
See also
--------
wdensity
References
----------
.. [1] Irgens, Fridtjov (1987)
"Formelsamling i mekanikk:
statikk, fasthetsl?re, dynamikk fluidmekanikk"
tapir forlag, University of Trondheim,
ISBN 82-519-0786-1, pp 19
'''
phir = phi * pi / 180. # change from degrees to radians
return 9.78049 * (1. + 0.0052884 * sin(phir) ** 2. - 0.0000059 * sin(2 * phir) ** 2.)
def nextpow2(x):
'''
Return next higher power of 2
Example
-------
>>> nextpow2(10)
4
>>> nextpow2(np.arange(5))
3
'''
t = isscalar(x) or len(x)
if (t > 1):
f, n = frexp(t)
else:
f, n = frexp(abs(x))
if (f == 0.5):
n = n - 1
return n
def discretize(fun, a, b, tol=0.005, n=5):
'''
Automatic discretization of function
Parameters
----------
fun : callable
function to discretize
a,b : real scalars
evaluation limits
tol : real, scalar
absoute error tolerance
n : scalar integer
number of values
Returns
-------
x : discretized values
y : fun(x)
Example
-------
>>> import numpy as np
>>> import pylab as plb
>>> x,y = discretize(np.cos,0,np.pi)
>>> t = plb.plot(x,y)
>>> plb.show()
>>> plb.close('all')
'''
tiny = floatinfo.tiny
x = linspace(a, b, n)
y = fun(x)
err0 = inf
err = 10000
nmax = 2 ** 20
while (err != err0 and err > tol and n < nmax):
err0 = err
x0 = x
y0 = y
n = 2 * (n - 1) + 1
x = linspace (a, b, n)
y = fun(x)
y00 = interp(x, x0, y0)
err = 0.5 * amax(abs((y00 - y) / (abs(y00 + y) + tiny)))
return x, y
def pol2cart(theta, rho):
'''
Transform polar coordinates into 2D cartesian coordinates.
Returns
-------
x, y : array-like
Cartesian coordinates, x = rho*cos(theta), y = rho*sin(theta)
See also
--------
cart2pol
'''
return rho * cos(theta), rho * sin(theta)
def cart2pol(x, y):
''' Transform 2D cartesian coordinates into polar coordinates.
Returns
-------
theta : array-like
arctan2(y,x)
rho : array-like
sqrt(x**2+y**2)
See also
--------
pol2cart
'''
return arctan2(y, x), hypot(x, y)
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
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.
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
--------
>>> x = np.linspace(0,1,3) # coordinates along x axis
>>> y = np.linspace(0,1,2) # coordinates along y axis
>>> xv, yv = meshgrid(x,y) # extend x and y for a 2D xy grid
>>> 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(x,y,sparse=True,indexing='ij') # change to matrix indexing
[array([[ 0. ],
[ 0.5],
[ 1. ]]), array([[ 0., 1.]])]
>>> meshgrid(x,y,indexing='ij')
[array([[ 0. , 0. ],
[ 0.5, 0.5],
[ 1. , 1. ]]), array([[ 0., 1.],
[ 0., 1.],
[ 0., 1.]])]
>>> meshgrid(0,1,5) # just a 3D point
[array([[[0]]]), array([[[1]]]), array([[[5]]])]
>>> map(np.squeeze,meshgrid(0,1,5)) # just a 3D point
[array(0), array(1), array(5)]
>>> meshgrid(3)
array([3])
>>> meshgrid(y) # 1D grid y is just returned
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)
"""
copy = kwargs.get('copy', True)
args = atleast_1d(*xi)
if not isinstance(args, list):
if args.size > 0:
return args.copy() if copy else args
else:
raise TypeError('meshgrid() take 1 or more arguments (0 given)')
sparse = kwargs.get('sparse', False)
indexing = kwargs.get('indexing', 'xy') # 'ij'
ndim = len(args)
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 = ones(shape, dtype=int)
return [x * mult_fact for x in output]
else:
return 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)
def trangood(x, f, min_n=None, min_x=None, max_x=None, max_n=inf):
"""
Make sure transformation is efficient.
Parameters
------------
x, f : array_like
input transform function, (x,f(x)).
min_n : scalar, int
minimum number of points in the good transform.
(Default x.shape[0])
min_x : scalar, real
minimum x value to transform. (Default min(x))
max_x : scalar, real
maximum x value to transform. (Default max(x))
max_n : scalar, int
maximum number of points in the good transform
(default inf)
Returns
-------
x, f : array_like
the good transform function.
TRANGOOD interpolates f linearly and optionally
extrapolate it linearly outside the range of x
with X uniformly spaced.
See also
---------
tranproc,
numpy.interp
"""
xo, fo = atleast_1d(x, f)
#n = xo.size
if (xo.ndim != 1):
raise ValueError('x must be a vector.')
if (fo.ndim != 1):
raise ValueError('f must be a vector.')
i = xo.argsort()
xo = xo[i]
fo = fo[i]
del i
dx = diff(xo)
if (any(dx <= 0)):
raise ValueError('Duplicate x-values not allowed.')
nf = fo.shape[0]
if max_x is None:
max_x = xo[-1]
if min_x is None:
min_x = xo[0]
if min_n is None:
min_n = nf
if (min_n < 2):
min_n = 2
if (max_n < 2):
max_n = 2
ddx = diff(dx)
xn = xo[-1]
x0 = xo[0]
L = float(xn - x0)
eps = floatinfo.eps
if ((nf < min_n) or (max_n < nf) or any(abs(ddx) > 10 * eps * (L))):
## % pab 07.01.2001: Always choose the stepsize df so that
## % it is an exactly representable number.
## % This is important when calculating numerical derivatives and is
## % accomplished by the following.
dx = L / (min(min_n, max_n) - 1)
dx = (dx + 2.) - 2.
xi = arange(x0, xn + dx / 2., dx)
#% New call pab 11.11.2000: This is much quicker
fo = interp(xi, xo, fo)
xo = xi
# x is now uniformly spaced
dx = xo[1] - xo[0]
# Extrapolate linearly outside the range of ff
if (min_x < xo[0]):
x1 = dx * arange(floor((min_x - xo[0]) / dx), -2)
f2 = fo[0] + x1 * (fo[1] - fo[0]) / (xo[1] - xo[0])
fo = hstack((f2, fo))
xo = hstack((x1 + xo[0], xo))
if (max_x > xo[-1]):
x1 = dx * arange(1, ceil((max_x - xo[-1]) / dx) + 1)
f2 = f[-1] + x1 * (f[-1] - f[-2]) / (xo[-1] - xo[-2])
fo = hstack((fo, f2))
xo = hstack((xo, x1 + xo[-1]))
return xo, fo
def tranproc(x, f, x0, * xi):
"""
Transforms process X and up to four derivatives
using the transformation f.
Parameters
----------
x,f : array-like
[x,f(x)], transform function, y = f(x).
x0, x1,...,xn : vectors
where xi is the i'th time derivative of x0. 0<=N<=4.
Returns
-------
y0, y1,...,yn : vectors
where yi is the i'th time derivative of y0 = f(x0).
By the basic rules of derivation:
Y1 = f'(X0)*X1
Y2 = f''(X0)*X1^2 + f'(X0)*X2
Y3 = f'''(X0)*X1^3 + f'(X0)*X3 + 3*f''(X0)*X1*X2
Y4 = f''''(X0)*X1^4 + f'(X0)*X4 + 6*f'''(X0)*X1^2*X2
+ f''(X0)*(3*X2^2 + 4*X1*X3)
The derivation of f is performed numerically with a central difference
method with linear extrapolation towards the beginning and end of f,
respectively.
Example
--------
Derivative of g and the transformed Gaussian model.
>>> import pylab as plb
>>> import wafo.transform.models as wtm
>>> tr = wtm.TrHermite()
>>> x = linspace(-5,5,501)
>>> g = tr(x)
>>> gder = tranproc(x, g, x, ones(g.shape[0]))
>>> h = plb.plot(x, g, x, gder[1])
plb.plot(x,pdfnorm(g)*gder[1],x,pdfnorm(x))
plb.legend('Transformed model','Gaussian model')
>>> plb.close('all')
See also
--------
trangood.
"""
eps = floatinfo.eps
xo, fo, x0 = atleast_1d(x, f, x0)
xi = atleast_1d(*xi)
if not isinstance(xi, list):
xi = [xi,]
N = len(xi) # N = number of derivatives
nmax = ceil((xo.ptp()) * 10 ** (7. / max(N, 1)))
xo, fo = trangood(xo, fo, min_x=min(x0), max_x=max(x0), max_n=nmax)
n = f.shape[0]
#y = x0.copy()
xu = (n - 1) * (x0 - xo[0]) / (xo[-1] - xo[0])
fi = asarray(floor(xu), dtype=int)
fi = where(fi == n - 1, fi - 1, fi)
xu = xu - fi
y0 = fo[fi] + (fo[fi + 1] - fo[fi]) * xu
y = y0
if N > 0:
y = [y0]
hn = xo[1] - xo[0]
if hn ** N < sqrt(eps):
print('Numerical problems may occur for the derivatives in tranproc.')
warnings.warn('The sampling of the transformation may be too small.')
#% Transform X with the derivatives of f.
fxder = zeros((N, x0.size))
fder = vstack((xo, fo)).T
for k in range(N): #% Derivation of f(x) using a difference method.
n = fder.shape[0]
#%fder = [(fder(1:n-1,1)+fder(2:n,1))/2 diff(fder(:,2))./diff(fder(:,1))]
fder = vstack([(fder[0:n - 1, 0] + fder[1:n, 0]) / 2, diff(fder[:, 1]) / hn])
fxder[k] = tranproc(fder[0], fder[1], x0)
#% Calculate the transforms of the derivatives of X.
#% First time derivative of y: y1 = f'(x)*x1
y1 = fxder[0] * xi[0]
y.append(y1)
if N > 1:
# Second time derivative of y:
# y2 = f''(x)*x1.^2+f'(x)*x2
y2 = fxder[1] * xi[0] ** 2. + fxder[0] * xi[1]
y.append(y2)
if N > 2:
# Third time derivative of y:
# y3 = f'''(x)*x1.^3+f'(x)*x3 +3*f''(x)*x1*x2
y3 = fxder[2] * xi[0] ** 3 + fxder[0] * xi[2] + \
3 * fxder[1] * xi[0] * xi[1]
y.append(y3)
if N > 3:
# Fourth time derivative of y:
# y4 = f''''(x)*x1.^4+f'(x)*x4
# +6*f'''(x)*x1^2*x2+f''(x)*(3*x2^2+4x1*x3)
y4 = (fxder[3] * xi[0] ** 4. + fxder[0] * xi[3] + \
6. * fxder[2] * xi[0] ** 2. * xi[1] + \
fxder[1] * (3. * xi[1] ** 2. + 4. * xi[0] * xi[1]))
y.append(y4)
if N > 4:
warnings.warn('Transformation of derivatives of order>4 not supported.')
return y #0,y1,y2,y3,y4
def test_common_shape():
A = ones((4, 1))
B = 2
C = ones((1, 5)) * 5
common_shape(A, B, C)
common_shape(A, B, C, shape=(3, 4, 1))
A = ones((4, 1))
B = 2
C = ones((1, 5)) * 5
common_shape(A, B, C, shape=(4, 5))
def test_meshgrid():
x = array([-1, -0.5, 1, 4, 5], float)
y = array([0, -2, -5], float)
xv, yv = meshgrid(x, y, sparse=False)
print(xv)
print(yv)
xv, yv = meshgrid(x, y, sparse=True) # make sparse output arrays
print(xv)
print(yv)
print(meshgrid(0, 1, 5, sparse=True)) # just a 3D point
print(meshgrid([0, 1, 5], sparse=True)) # just a 3D point
xv, yv = meshgrid(y, y)
yv[0, 0] = 10
print(xv)
print(yv)
## >>> xv
## array([[ 0. , 0.5, 1. ]])
## >>> yv
## array([[ 0.],
## [ 1.]])
## array([[-1. , -0.5, 1. , 4. , 5. ],
## [-1. , -0.5, 1. , 4. , 5. ],
## [-1. , -0.5, 1. , 4. , 5. ]])
##
## array([[ 0., 0., 0., 0., 0.],
## [-2., -2., -2., -2., -2.],
## [-5., -5., -5., -5., -5.]])
def _test_tranproc():
import wafo.transform.models as wtm
tr = wtm.TrHermite()
x = linspace(-5, 5, 501)
g = tr(x)
gder = tranproc(x, g, x, ones(g.size))
pass
#>>> gder(:,1) = g(:,1)
#>>> plot(g(:,1),[g(:,2),gder(:,2)])
#>>> plot(g(:,1),pdfnorm(g(:,2)).*gder(:,2),g(:,1),pdfnorm(g(:,1)))
#>>> legend('Transformed model','Gaussian model')
def _test_detrend():
import pylab as plb
cos = plb.cos;randn = plb.randn
x = linspace(0, 1, 200)
y = exp(x) + cos(5 * 2 * pi * x) + 1e-1 * randn(x.size)
y0 = detrendma(y, 20);tr = y - y0
plb.plot(x, y, x, y0, 'r', x, exp(x), 'k', x, tr, 'm')
def _test_extrema():
import pylab as pb
from pylab import plot
t = pb.linspace(0, 7 * pi, 250)
x = pb.sin(t) + 0.1 * sin(50 * t)
ind = findextrema(x)
ti, tp = t[ind], x[ind]
plot(t, x, '.', ti, tp, 'r.')
ind1 = findrfc(tp, 0.3)
def _test_discretize():
import pylab as plb
x, y = discretize(cos, 0, pi)
plb.plot(x, y)
plb.show()
plb.close('all')
def _test_stirlerr():
x = linspace(1, 5, 6)
print stirlerr(x)
print stirlerr(1)
print getshipchar(1000)
print betaloge(3, 2)
def _test_parse_kwargs():
opt = dict(arg1=1, arg2=3)
print opt
opt = parse_kwargs(opt, arg1=5)
print opt
opt2 = dict(arg3=15)
opt = parse_kwargs(opt, **opt2)
print opt
opt0 = testfun('default')
print opt0
opt0.update(opt1=100)
print opt0
opt0 = parse_kwargs(opt0, opt2=200)
print opt0
out1 = testfun(opt0['opt1'], **opt0)
print out1
if __name__ == "__main__":
if True:# False: #
import doctest
doctest.testmod()
else:
_test_tranproc()