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.

212 lines
6.9 KiB
Matlab

7 years ago
function [bss, rmse, dVc, dVm, ddV] = fsbeach_modelskill(measured, computed, initial)
%edited by Joshua Simmons 04/04/2016 to revise definitions of r2 etc
%XB_SKILL Computes a variety skill scores
%
% Computes a variety skill scores: R^2, Sci, Relative bias, Brier Skill
% Score. Special feature: within the XBeach testbed, the results are
% stored to be able to show the development of the different skill scores
% in time.
%
% Syntax:
% [r2 sci relbias bss] = xb_skill(measured, computed, varargin)
%
% Input:
% measured = Measured data where the first column contains independent
% values and the second column contains dependent values
% computed = Computed data where the first column contains independent
% values and the second column contains dependent values
% initial = Initial data where the first column contains independent
% values and the second column contains dependent values
% varargin = var: Name of the variable that is supplied
%
% Output:
% bss = Brier Skill Score
% rb20 = Regression through origin R2 value
%
% Example
% [r2 sci relbias bss] = xb_skill(measured, computed)
% [r2 sci relbias bss] = xb_skill(measured, computed, 'var', 'zb')
%
% See also xb_plot_skill
%% Copyright notice
% --------------------------------------------------------------------
% Copyright (C) 2011 Deltares
% Bas Hoonhout
%
% bas.hoonhout@deltares.nl
%
% Rotterdamseweg 185
% 2629HD Delft
%
% This library is free software: you can redistribute it and/or
% modify it under the terms of the GNU Lesser General Public
% License as published by the Free Software Foundation, either
% version 2.1 of the License, or (at your option) any later version.
%
% This library is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
% Lesser General Public License for more details.
%
% You should have received a copy of the GNU Lesser General Public
% License along with this library. If not, see <http://www.gnu.org/licenses/>.
% --------------------------------------------------------------------
% This tool is part of <a href="http://OpenEarth.nl">OpenEarthTools</a>.
% OpenEarthTools is an online collaboration to share and manage data and
% programming tools in an open source, version controlled environment.
% Sign up to recieve regular updates of this function, and to contribute
% your own tools.
%% Version <http://svnbook.red-bean.com/en/1.5/svn.advanced.props.special.keywords.html>
% Created: 13 Apr 2011
% Created with Matlab version: 7.9.0.529 (R2009b)
% $Id: xb_skill.m 4725 2011-06-27 12:58:48Z hoonhout $
% $Date: 2011-06-27 14:58:48 +0200 (ma, 27 jun 2011) $
% $Author: hoonhout $
% $Revision: 4725 $
% $HeadURL: https://repos.deltares.nl/repos/OpenEarthTools/trunk/matlab/applications/xbeach/xb_analysis/xb_skill.m $
% $Keywords: $
%% read options
if ~exist('initial', 'var'); initial = []; end;
%% xbeach bugfix
% bug - sometime xbeach has suprious points on the end (a flat end to
% the profile) this is fake so remove it.
if length(computed)>=10
if nanmean(computed(1:10,2)) < nanmean(computed(end-9:end,2))
%xbeach direction
spr_len = length(diff(computed(:,2))) - find(diff(computed(:,2))~=0,1,'last');
computed(end-spr_len+1:end,2) = NaN;
else
spr_len = find(diff(computed(:,2))~=0,1,'first');
computed(1:spr_len-1,2) = NaN;
end
if spr_len > 2
disp(['Warning check computed points, ' num2str(spr_len) ' points found to be spurious'] )
end
end
%% remove nans
measured = measured(~any(isnan(measured), 2),:);
computed = computed(~any(isnan(computed), 2),:);
if ~isempty(initial)
initial = initial (~any(isnan(initial ), 2),:);
end
%% compute skills
[bss rmse dVc dVm ddV] = deal(nan);
if size(measured,1) > 1 && size(computed,1) > 1
x = unique([computed(:,1) ; measured(:,1)]);
x = x(~isnan(x));
zmt = interp1(measured(:,1), measured(:,2), x);
zct = interp1(computed(:,1), computed(:,2), x);
% determine active zone
if ~isempty(initial)
zit = interp1(initial(:,1), initial(:,2), x);
%average over 10 steps for small spikes
dzmi = smooth(abs(zmt-zit),10);
dzmi((isnan(zmt)|isnan(zit))) = 0;
dzcm = smooth(abs(zct-zmt),10);
dzcm((isnan(zct)|isnan(zmt))) = 0;
dz = max(dzmi,dzcm);
%has to be more change than a standard measurement error (10cm say)
zi1 = find(dz>0.1,1,'first');
zi2 = find(dz>0.1,1,'last');
x = x (zi1:zi2);
zmt = zmt(zi1:zi2);
zct = zct(zi1:zi2);
zit = zit(zi1:zi2);
end
%% clear all nan values in input (to avoid problems with interpolation)
%all equal at this point and assign values for BSS calc
x0 = x;
xc = x;
xm = x;
z0 = zit;
zc = zct;
zm = zmt;
x0(isnan(z0)) = [];
z0(isnan(z0)) = [];
xc(isnan(zc)) = [];
zc(isnan(zc)) = [];
xm(isnan(zm)) = [];
zm(isnan(zm)) = [];
%% determine new grid covered by all profiles
x_new = unique([x0' xc' xm']);
%% interpolate profiles onto new grid
[x0,id1] = unique(x0);
[xc,id2] = unique(xc);
[xm,id3] = unique(xm);
z0 = z0(id1);
zc = zc(id2);
zm = zm(id3);
z0_new = interp1(x0, z0, x_new);
zc_new = interp1(xc, zc, x_new);
zm_new = interp1(xm, zm, x_new);
% reduce vectors if any nans are left
id = ~(isnan(z0_new) | isnan(zc_new) | isnan(zm_new));
[x_new z0_new zc_new zm_new] = deal(x_new(id), z0_new(id), zc_new(id), zm_new(id));
%% Calculate volume change
try
Vc = volumefind(x_new,zc_new,0);
Vm = volumefind(x_new,zm_new,0);
V0 = volumefind(x_new,z0_new,0);
dVm = Vm-V0; %measured volume change
dVc = Vc-V0; %computed volume change
ddV = dVc-dVm; %predicted volume change - measured
nddV = ddV/abs(V0-Vm);
catch
dVm = NaN;
dVc = NaN;
ddV = NaN;
nddV = NaN;
end
%% derive weight
% weight is defined as half of diff left and half of diff right of each
% point; first and last point are considered to have only one side.
weight = diff([x_new(1) diff(x_new)/2 + x_new(1:end-1) x_new(end)]);
weight = weight / sum(weight);
%% calculate BSS only
% brier skill score
if ~isempty(initial)
mse_p = sum( (zm_new - zc_new).^2 .* weight );
mse_0 = sum( (zm_new - z0_new).^2 .* weight );
bss = 1. - (mse_p/mse_0);
else
bss = 1-(std(zc-zm))^2/var(zm);
end
%% Calculate others
rmse = sqrt(mean((zc_new-zm_new).^2));
rmsm = sqrt(mean(zm_new.^2));
sci = rmse/max(rmsm,abs(mean(zm_new)));
relbias = mean(zc_new-zm_new)/max(rmsm,abs(mean(zm_new)));
end