From d20cb4dac19dcf015aa3fda54c469a9b2c192337 Mon Sep 17 00:00:00 2001 From: "per.andreas.brodtkorb" Date: Thu, 15 Dec 2011 06:54:20 +0000 Subject: [PATCH] Updates to smoothn --- pywafo/src/wafo/kdetools.py | 426 +++++++++++++++++------------------- 1 file changed, 204 insertions(+), 222 deletions(-) diff --git a/pywafo/src/wafo/kdetools.py b/pywafo/src/wafo/kdetools.py index d822980..588c190 100644 --- a/pywafo/src/wafo/kdetools.py +++ b/pywafo/src/wafo/kdetools.py @@ -15,6 +15,7 @@ from misc import tranproc #, trangood from numpy import pi, sqrt, atleast_2d, exp, newaxis #@UnresolvedImport from scipy import interpolate, linalg, sparse from scipy.special import gamma +from scipy.ndimage.morphology import distance_transform_edt import scipy.special as special import scipy.optimize as optimize from wafo.misc import meshgrid, nextpow2 @@ -3027,233 +3028,214 @@ def unfinished_smoothn(data,s=None, weight=None, robust=False, z0=None, tolz=1e- # Weights. Zero weights are assigned to not finite values (Inf or NaN), # (Inf/NaN values = missing data). - IsFinite = np.isfinite(y); - nof = sum(IsFinite) # number of finite elements - W = W*IsFinite - if any(W<0): + IsFinite = np.isfinite(y) + nof = IsFinite.sum() # number of finite elements + W = W * IsFinite + if (W<0).any(): raise ValueError('Weights must all be >=0') else: W = W/W.max() + # Weighted or missing data? + isweighted = (W<1).any() + + + # Automatic smoothing? + isauto = s is None + # Creation of the Lambda tensor + # Lambda contains the eingenvalues of the difference matrix used in this + # penalized least squares process. + d = y.ndim + Lambda = zeros(sizy) + siz0 = (1,)*d + for i in range(d): + siz0[i] = sizy(i) + Lambda = Lambda + cos(pi*np.arange(sizy(i))/sizy[i]).reshape(siz0) + siz0[i] = 1 + + Lambda = -2*(d-Lambda) + if not isauto: + Gamma = 1./(1 + s * Lambda ** 2) + + # Upper and lower bound for the smoothness parameter + # The average leverage (h) is by definition in [0 1]. Weak smoothing occurs + # if h is close to 1, while over-smoothing appears when h is near 0. Upper + # and lower bounds for h are given to avoid under- or over-smoothing. See + # equation relating h to the smoothness parameter (Equation #12 in the + # referenced CSDA paper). + N = (np.array(sizy)!=1).sum() # tensor rank of the y-array + hMin = 1e-6; + hMax = 0.99; + sMinBnd = (((1+sqrt(1+8*hMax**(2/N)))/4./hMax**(2/N))**2-1)/16 + sMaxBnd = (((1+sqrt(1+8*hMin**(2/N)))/4./hMin**(2/N))**2-1)/16 + + # Initialize before iterating + + Wtot = W; + # Initial conditions for z + if weight is None: + z = zeros(sizy) + else: + # With weighted/missing data + # An initial guess is provided to ensure faster convergence. For that + # purpose, a nearest neighbor interpolation followed by a coarse + # smoothing are performed. + + if z0 is None: + z = InitialGuess(y,IsFinite); + else: + # an initial guess (z0) has been provided + z = z0 + z0 = z + y[1-IsFinite] = 0 # arbitrary values for missing y-data + + tol = 1 + RobustIterativeProcess = True + RobustStep = 1; + nit = 0; + # Error on p. Smoothness parameter s = 10^p + errp = 0.1; + opt = optimset('TolX',errp); + # Relaxation factor RF: to speedup convergence + RF = 1 + 0.75 if weight else 1.0 + + # Main iterative process + while RobustIterativeProcess + # "amount" of weights (see the function GCVscore) + aow = Wtot.sum()/noe # 0 < aow <= 1 + + while tol>TolZ && nit tol=0 (no iteration) + tol = norm(z0(:)-z(:))/norm(z(:)) if weight else 0.0 + + z0 = z # re-initialization + end + exitflag = nit0.9: # aow = 1 means that all of the data are equally weighted + # very much faster: does not require any inverse DCT + RSS = norm(DCTy.ravel()*(Gamma.ravel()-1))**2 + else: + # take account of the weights to calculate RSS: + yhat = idctn(Gamma*DCTy) + RSS = norm(sqrt(Wtot[IsFinite])*(y[IsFinite]-yhat[IsFinite]))**2 + end + + TrH = Gamma.sum() + GCVscore = RSS/nof/(1.0-TrH/noe)**2 + return GCVScore + + + # Robust weights + def RobustWeights(r,I,h,wstr): + #weights for robust smoothing. + MAD = median(abs(r[I]-median(r[I]))) # median absolute deviation + u = abs(r/(1.4826*MAD)/sqrt(1-h)) # studentized residuals + if wstr == 'cauchy': + c = 2.385; + W = 1./(1+(u/c).^2); % Cauchy weights + elif wstr=='talworth': + c = 2.795; + W = uTolZ && nit tol=0 (no iteration) -# tol = isweighted*norm(z0(:)-z(:))/norm(z(:)); -# -# z0 = z; % re-initialization -# end -# exitflag = nit0.9 % aow = 1 means that all of the data are equally weighted -# % very much faster: does not require any inverse DCT -# RSS = norm(DCTy(:).*(Gamma(:)-1))^2; -# else -# % take account of the weights to calculate RSS: -# yhat = idctn(Gamma.*DCTy); -# RSS = norm(sqrt(Wtot(IsFinite)).*(y(IsFinite)-yhat(IsFinite)))^2; -# end -# %--- -# TrH = sum(Gamma(:)); -# GCVscore = RSS/nof/(1-TrH/noe)^2; -# end -# -# end -# -# %% Robust weights -# function W = RobustWeights(r,I,h,wstr) -# % weights for robust smoothing. -# MAD = median(abs(r(I)-median(r(I)))); % median absolute deviation -# u = abs(r/(1.4826*MAD)/sqrt(1-h)); % studentized residuals -# if strcmp(wstr,'cauchy') -# c = 2.385; W = 1./(1+(u/c).^2); % Cauchy weights -# elseif strcmp(wstr,'talworth') -# c = 2.795; W = uhere.']) -# elseif ~exist('idctn','file') -# error('MATLAB:smoothn:MissingFunction',... -# ['DCTN and IDCTN are required. Download IDCTN here.']) -# end -# end -# -# %% Initial Guess with weighted/missing data -# function z = InitialGuess(y,I) -# %-- nearest neighbor interpolation (in case of missing values) -# if any(~I(:)) -# if license('test','image_toolbox') -# [z,L] = bwdist(I); -# z = y; -# z(~I) = y(L(~I)); -# else -# % If BWDIST does not exist, NaN values are all replaced with the -# % same scalar. The initial guess is not optimal and a warning -# % message thus appears. -# z = y; -# z(~I) = mean(y(I)); -# warning('MATLAB:smoothn:InitialGuess',... -# ['BWDIST (Image Processing Toolbox) does not exist. ',... -# 'The initial guess may not be optimal; additional',... -# ' iterations can thus be required to ensure complete',... -# ' convergence. Increase ''MaxIter'' criterion if necessary.']) -# end -# else -# z = y; -# end -# %-- coarse fast smoothing using one-tenth of the DCT coefficients -# siz = size(z); -# z = dctn(z); -# for k = 1:ndims(z) -# z(ceil(siz(k)/10)+1:end,:) = 0; -# z = reshape(z,circshift(siz,[0 1-k])); -# z = shiftdim(z,1); -# end -# z = idctn(z); -# end - def kde_demo1(): '''