Home > TOSSH > TOSSH_code > utility_functions > util_FitPowerLaw.m

util_FitPowerLaw

PURPOSE ^

util_FitPowerLaw fits a power law (to recession segments).

SYNOPSIS ^

function [a, b, error_flag, error_str] =util_FitPowerLaw(Q_rec, dQdt_rec, fitting_type, weights)

DESCRIPTION ^

util_FitPowerLaw fits a power law (to recession segments).
   dQ/dt = -a*Q^b
   Different options are available (e.g. linear fitting in loglog-space,
   non-linear, or fitting a fixed slope).

   INPUT
   Q_rec: streamflow (recession periods only)
   dQdt_rec: corresponding flow rate gradients
   fitting_type: specifies fitting procedure: linear, non-linear, linear
       with slope 1, linear with slope 2
   weights: weights to fit curve

   OUTPUT
   a: scaling parameter
   b: parameter of non-linearity
   error_flag: 0 (no error), 1 (warning), 2 (errorin data check), 3
       (error in signature calculation)
   error_str: string contraining error description

   EXAMPLE
   % load example data
   data = load('example/example_data/33029_daily.mat');
   Q = data.Q;
   t = data.t;
   flow_section = util_RecessionSegments(Q,t,'plot_results',true); % get recession segments
   [dQdt, Qm, flow_section, R2] = util_dQdt(Q, t, flow_section); % get flow rate gradient
   rec = ~isnan(Qm);
   [a, b] = util_FitPowerLaw(Qm(rec), dQdt(rec));
   [a, b] = util_FitPowerLaw(Qm(rec), dQdt(rec), 'fitting_type', 'linear', 'weights', R2(rec))

   Copyright (C) 2020
   This software is distributed under the GNU Public License Version 3.
   See <https://www.gnu.org/licenses/gpl-3.0.en.html> for details.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [a, b, error_flag, error_str] = ...
0002     util_FitPowerLaw(Q_rec, dQdt_rec, fitting_type, weights)
0003 %util_FitPowerLaw fits a power law (to recession segments).
0004 %   dQ/dt = -a*Q^b
0005 %   Different options are available (e.g. linear fitting in loglog-space,
0006 %   non-linear, or fitting a fixed slope).
0007 %
0008 %   INPUT
0009 %   Q_rec: streamflow (recession periods only)
0010 %   dQdt_rec: corresponding flow rate gradients
0011 %   fitting_type: specifies fitting procedure: linear, non-linear, linear
0012 %       with slope 1, linear with slope 2
0013 %   weights: weights to fit curve
0014 %
0015 %   OUTPUT
0016 %   a: scaling parameter
0017 %   b: parameter of non-linearity
0018 %   error_flag: 0 (no error), 1 (warning), 2 (errorin data check), 3
0019 %       (error in signature calculation)
0020 %   error_str: string contraining error description
0021 %
0022 %   EXAMPLE
0023 %   % load example data
0024 %   data = load('example/example_data/33029_daily.mat');
0025 %   Q = data.Q;
0026 %   t = data.t;
0027 %   flow_section = util_RecessionSegments(Q,t,'plot_results',true); % get recession segments
0028 %   [dQdt, Qm, flow_section, R2] = util_dQdt(Q, t, flow_section); % get flow rate gradient
0029 %   rec = ~isnan(Qm);
0030 %   [a, b] = util_FitPowerLaw(Qm(rec), dQdt(rec));
0031 %   [a, b] = util_FitPowerLaw(Qm(rec), dQdt(rec), 'fitting_type', 'linear', 'weights', R2(rec))
0032 %
0033 %   Copyright (C) 2020
0034 %   This software is distributed under the GNU Public License Version 3.
0035 %   See <https://www.gnu.org/licenses/gpl-3.0.en.html> for details.
0036 
0037 if nargin < 2
0038     error('Not enough input arguments.')
0039 elseif nargin < 3
0040     fitting_type = 'linear';
0041 elseif nargin < 4
0042     weights = ones(size(Q_rec));
0043 end
0044 
0045 % default setting reads as good data
0046 error_flag = 0;
0047 error_str = '';
0048 
0049 % data checks
0050 if all(isnan(Q_rec)) || all(isnan(dQdt_rec))
0051     a = NaN;
0052     b = NaN;
0053     error_flag = 1;
0054     error_str = ['Warning: Some recessions consist only of NaN values (possibly because eps > 0). ', error_str];
0055     return
0056 end
0057 
0058 if strcmp(fitting_type, 'linear') % weighted linear regression in log log space
0059     
0060     A = [ones(size(Q_rec)), log(Q_rec)];
0061     P = (weights.*A)\(weights.*log(-dQdt_rec));
0062     a = exp(P(1));
0063     b = P(2);
0064     
0065     %{
0066     linFcn = @(p,x) p(2).*x + p(1);
0067     p0 = [0.1, 1.0];
0068     fit_nonlin = fitnlm(log(Q_rec),log(-dQdt_rec),linFcn,p0,'Weight',weights);
0069     a = exp(fit_nonlin.Coefficients.Estimate(1));
0070     b = fit_nonlin.Coefficients.Estimate(2);
0071     %}
0072     
0073 elseif strcmp(fitting_type, 'nonlinear') % weighted nonlinear regression in lin space
0074     
0075     powerFcn = @(p,x) p(1).*x.^p(2);
0076     p0 = [0.1, 1.0];
0077     fit_nonlin = fitnlm(Q_rec,-dQdt_rec,powerFcn,p0,'Weight',weights);
0078     a = fit_nonlin.Coefficients.Estimate(1);
0079     b = fit_nonlin.Coefficients.Estimate(2);
0080     
0081 elseif strcmp(fitting_type, 'slope1') % linear regression in log log space with fixed slope 1
0082     
0083     A = [ones(size(Q_rec))];
0084     b = 1;
0085     B = log(-dQdt_rec) - b*log(Q_rec);
0086     a = exp((weights.*A)\(weights.*B));
0087     
0088 elseif strcmp(fitting_type, 'slope2') % linear regression in log log space with fixed slope 2
0089     
0090     A = [ones(size(Q_rec))];
0091     b = 2;
0092     B = log(-dQdt_rec) - b*log(Q_rec);
0093     a = exp((weights.*A)\(weights.*B));
0094     
0095 else
0096     error('Invalid fitting type.')
0097 end
0098 
0099 end
0100 
0101

Generated on Tue 02-Feb-2021 09:27:04 by m2html © 2005