% Transform AxTandem into Array (necessary for splitapply)
Z.Time = datenum(Z.Time);
for i = 1:length(ClassType)
% Filter based on Class - AxTandem is compromised after this (deleting entries)
if strcmp(Class,'ClassOW')
AxTandem(AxTandem.CLASS == 0,:) = [];
elseif strcmp(Class,'Class')
AxTandem(AxTandem.CLASS == 0,:) = [];
AxTandem(AxTandem.CLASS > 39 & AxTandem.CLASS < 50,:) = [];
Z(Z(:,5) > 39 & Z(:,5) < 50,:) = [];
Max.(Class).(BlockM) = [];
if strcmp(BlockM,'Daily')
% Make groups out of unique locations and days
[Gr, GrIDDay, GrIDZST] = findgroups(dateshift(AxTandem.Time,'start','day'),AxTandem.ZST);
elseif strcmp(BlockM,'Weekly')
[Gr, GrIDWeek, GrIDZST] = findgroups(dateshift(AxTandem.Time,'start','week'),AxTandem.ZST);
[Gr, GrIDYear, GrIDZST] = findgroups(year(AxTandem.Time),AxTandem.ZST);
% Perform splitapply (see function at end... not just Max as we want whole rows involving maxes)
Max.(Class).(BlockM) = splitapply(@(Z)maxIndex(Z),Z,Gr);
% Transform back into table form
Max.(Class).(BlockM) = array2table(Max.(Class).(BlockM));
Max.(Class).(BlockM).Properties.VariableNames = {'Max','AWT1kN','AWT2kN','W1_2M','ZST','CLASS','Time'};
Max.(Class).(BlockM).Time = datetime(Max.(Class).(BlockM).Time,'ConvertFrom',"datenum");
DistTypes = {'Normal', 'Lognormal', 'GeneralizedExtremeValue'};
% Set CDF Scaling Factors for estimates
D2WFactor = 5; W2YFactor = 50; D2YFactor = D2WFactor*W2YFactor;
% Set x values to be use globally
% Fit Block Maxima to Normal Curve
for i = 1:length(ClassType)
for k = 1:length(DistTypes)
pd.(Class).(BlockM).(Dist) = fitdist(Max.(Class).(BlockM).Max/2,Dist);
y_values.(Class).(BlockM).(Dist).PDF_Fit = pdf(pd.(Class).(BlockM).(Dist),x_values);
y_values.(Class).(BlockM).(Dist).CDF_Fit = cdf(pd.(Class).(BlockM).(Dist),x_values);
if strcmp(BlockM,'Daily')
y_values.(Class).('Weekly').(Dist).CDF_D2W = y_values.(Class).(BlockM).(Dist).CDF_Fit.^D2WFactor;
y_values.(Class).('Weekly').(Dist).PDF_D2W = [0 diff(y_values.(Class).('Weekly').(Dist).CDF_D2W)];
y_values.(Class).('Yearly').(Dist).CDF_D2Y = y_values.(Class).(BlockM).(Dist).CDF_Fit.^D2YFactor;
y_values.(Class).('Yearly').(Dist).PDF_D2Y = [0 diff(y_values.(Class).('Yearly').(Dist).CDF_D2Y)];
mu = trapz(y_values.(Class).('Weekly').(Dist).CDF_D2W,x_values);
sigma = sqrt(trapz(y_values.(Class).('Weekly').(Dist).CDF_D2W,(x_values-mu).^2));
pd.(Class).D2W.(Dist) = makedist(Dist,"mu",mu,"sigma",sigma);
mu = trapz(y_values.(Class).('Yearly').(Dist).CDF_D2Y,x_values);
sigma = sqrt(trapz(y_values.(Class).('Yearly').(Dist).CDF_D2Y,(x_values-mu).^2));
pd.(Class).D2Y.(Dist) = makedist(Dist,"mu",mu,"sigma",sigma);
elseif strcmp(Dist,'Lognormal')
mu = trapz(y_values.(Class).('Weekly').(Dist).CDF_D2W,x_values);
sigma = sqrt(trapz(y_values.(Class).('Weekly').(Dist).CDF_D2W,(x_values-mu).^2));
zeta = sqrt(log(1+(sigma/mu)^2));
lambda = log(mu)-0.5*zeta^2;
pd.(Class).D2W.(Dist) = makedist(Dist,"mu",lambda,"sigma",zeta);
mu = trapz(y_values.(Class).('Yearly').(Dist).CDF_D2Y,x_values);
sigma = sqrt(trapz(y_values.(Class).('Yearly').(Dist).CDF_D2Y,(x_values-mu).^2));
zeta = sqrt(log(1+(sigma/mu)^2));
lambda = log(mu)-0.5*zeta^2;
pd.(Class).D2Y.(Dist) = makedist(Dist,"mu",lambda,"sigma",zeta);
elseif strcmp(BlockM,'Weekly')
y_values.(Class).('Yearly').(Dist).CDF_W2Y = y_values.(Class).(BlockM).(Dist).CDF_Fit.^W2YFactor;
y_values.(Class).('Yearly').(Dist).PDF_W2Y = [0 diff(y_values.(Class).('Yearly').(Dist).CDF_W2Y)];
mu = trapz(y_values.(Class).('Yearly').(Dist).CDF_W2Y,x_values);
sigma = sqrt(trapz(y_values.(Class).('Yearly').(Dist).CDF_W2Y,(x_values-mu).^2));
pd.(Class).W2Y.(Dist) = makedist(Dist,"mu",mu,"sigma",sigma);
elseif strcmp(Dist,'Lognormal')
mu = trapz(y_values.(Class).('Yearly').(Dist).CDF_W2Y,x_values);
sigma = sqrt(trapz(y_values.(Class).('Yearly').(Dist).CDF_W2Y,(x_values-mu).^2));
zeta = sqrt(log(1+(sigma/mu)^2));
lambda = log(mu)-0.5*zeta^2;
pd.(Class).W2Y.(Dist) = makedist(Dist,"mu",lambda,"sigma",zeta);
figure('Position',[0 0 1500 400]);
x = X(1:end-1) + diff(X);
for i = 1:length(ClassType)
y = histcounts(Max.(Class).(BlockM).Max/2,'BinEdges',X,'normalization','pdf');
bar(x,y/ScaleDown(j),1,'EdgeColor',C(j,:),'FaceColor',[.8 .8 .8],'FaceAlpha',0.5,'DisplayName',BlockM)
plot(x_values,y_values.(Class).(BlockM).(Dist).PDF_Fit/ScaleDown(j),'k-','DisplayName',[Dist 'Fit'])
if strcmp(BlockM,'Yearly')
plot(x_values,y_values.(Class).(BlockM).(Dist).PDF_D2Y/ScaleDown(j),'k--','DisplayName',[Dist 'D2Y'])
plot(x_values,y_values.(Class).(BlockM).(Dist).PDF_W2Y/ScaleDown(j),'k:','DisplayName',[Dist 'W2Y'])
set(gca,'ytick',[],'yticklabel',[],'ycolor','k')
xlim([LimitL+25 LimitR-25])
ylabel('Normalized Histograms')
xlabel('Total Tandem Load (kN) /2')
title(['Maximum Tandem Axles ' Class])
legend('location','northeast')
figure('Position',[0 0 1500 400]);
Xp = LimitL-Step/2:Step:LimitR-Step/2;
histogram(Max.All.(BlockM).Max/2,'BinEdges',Xp,'normalization','pdf','EdgeColor',C(4,:),'FaceColor',[.8 .8 .8],'FaceAlpha',0.2,'DisplayName','All')
histogram(Max.ClassOW.(BlockM).Max/2,'BinEdges',Xp,'normalization','pdf','EdgeColor',C(7,:),'FaceColor',[.8 .8 .8],'FaceAlpha',0.2,'DisplayName','ClassOW')
histogram(Max.Class.(BlockM).Max/2,'BinEdges',Xp,'normalization','pdf','EdgeColor',C(9,:),'FaceColor',[.8 .8 .8],'FaceAlpha',0.2,'DisplayName','Class')
set(gca,'ytick',[],'yticklabel',[])
ylabel('Normalized Histograms')
xlabel('Total Tandem Load (kN) /2')
title(['Maximum Tandem Axles ' BlockM])
legend('location','best')
xlim([LimitL+25 LimitR-25])
figure('Position',[0 0 1500 400]);
Xp = LimitL-Step/2:Step:LimitR-Step/2;
x = X(1:end-1) + diff(X);
for i = 1:length(ClassType)
y = histcounts(Max.(Class).(BlockM).W1_2M,'BinEdges',X,'normalization','pdf');
bar(x,y/ScaleDown(j),1,'EdgeColor',C(j,:),'FaceColor',[.8 .8 .8],'FaceAlpha',0.5,'DisplayName',BlockM)
set(gca,'ytick',[],'yticklabel',[],'ycolor','k')
xlim([LimitL+.25 LimitR-.25])
ylabel('Normalized Histograms')
xlabel('Total Tandem Load (kN) /2')
title(['Maximum Tandem Axles - Spacing ' Class])
legend('location','best')
% According to Annex C of SIA 269
Beta.Yearly = 4.7; % Here we use the Beta annual - so we should use annual max effects
Beta.Weekly = 5.44422; % See Tail Fitting > Beta Conversion
% Right now we assume a normal distribution in the Edact calculation. Also
SumTableNorm = array2table(zeros(6,length(BM)*length(ClassType)));
SumTableLogNormComp = array2table(zeros(5,length(BM)*length(ClassType)));
SumTableNorm.Properties.VariableNames = {[BM{3} ' ' ClassType{3}], [BM{3} ' ' ClassType{2}], [BM{3} ' ' ClassType{1}], [BM{2} ' ' ClassType{3}],...
[BM{2} ' ' ClassType{2}], [BM{2} ' ' ClassType{1}], [BM{1} ' ' ClassType{3}], [BM{1} ' ' ClassType{2}], [BM{1} ' ' ClassType{1}]};
SumTableLogNorm = SumTableNorm;
SumTableNorm.Properties.RowNames = {'Mu', 'Sigma', 'COV (%)', '95th %', 'Dist 95', 'AlphaQ'};
SumTableLogNorm.Properties.RowNames = {'Lambda', 'Zeta', '95th %', 'Dist 95', 'AlphaQN', 'AlphaQLN'};
SumTableLogNormComp.Properties.RowNames = {'Lambda', 'Zeta', '95th %', 'Dist 95', 'AlphaQLN Est'};
SumTableLogNormComp.Properties.VariableNames = {[BM{3} ' ' ClassType{3}], [BM{3} ' ' ClassType{2}], [BM{3} ' ' ClassType{1}], ['W2Y ' ClassType{3}],...
['W2Y ' ClassType{2}], ['W2Y ' ClassType{1}], ['D2Y ' ClassType{3}], ['D2Y ' ClassType{2}], ['D2Y ' ClassType{1}]};
for i = 1:length(ClassType)
Emact = mean(Max.(Class).(BlockM).Max/2);
Stdev = std(Max.(Class).(BlockM).Max/2);
N5 = prctile(Max.(Class).(BlockM).Max/2,95);
Dist95N = norminv(0.95,pd.(Class).(BlockM).Normal.mu,pd.(Class).(BlockM).Normal.sigma);
Dist95LN = logninv(0.95,pd.(Class).(BlockM).Lognormal.mu,pd.(Class).(BlockM).Lognormal.sigma);
EdactN = Emact*(1+Alpha*Beta.(BlockM)*COV);
AlphaQN = EdactN/(300*1.5);
EdactLN = Emact*exp(Alpha*Beta.(BlockM)*sqrt(Delta2)-0.5*Delta2);
AlphaQLN = EdactLN/(300*1.5);
SumTableNorm.([BlockM ' ' Class]) = [Emact; Stdev; 100*COV; N5; Dist95N; AlphaQN];
SumTableLogNorm.([BlockM ' ' Class]) = [pd.(Class).(BlockM).Lognormal.mu; pd.(Class).(BlockM).Lognormal.sigma; N5; Dist95LN; AlphaQN; AlphaQLN];
if strcmp(BlockM,'Weekly')
pdx = pd.(Class).W2Y.Lognormal;
Emact = exp(pdx.mu+0.5*Delta2);
SumTableLogNormComp.(['W2Y ' Class]) = [pdx.mu; pdx.sigma; prctile(Max.(Class).Yearly.Max/2,95); logninv(0.95,pdx.mu,pdx.sigma); Emact*exp(Alpha*Beta.Yearly*sqrt(Delta2)-0.5*Delta2)/(300*1.5)];
elseif strcmp(BlockM,'Daily')
pdx = pd.(Class).D2Y.Lognormal;
Emact = exp(pdx.mu+0.5*Delta2);
SumTableLogNormComp.(['D2Y ' Class]) = [pdx.mu; pdx.sigma; prctile(Max.(Class).Yearly.Max/2,95); logninv(0.95,pdx.mu,pdx.sigma); Emact*exp(Alpha*Beta.Yearly*sqrt(Delta2)-0.5*Delta2)/(300*1.5)];
SumTableLogNormComp.([BlockM ' ' Class]) = [pd.(Class).(BlockM).Lognormal.mu; pd.(Class).(BlockM).Lognormal.sigma; N5; Dist95LN; AlphaQLN];
disp(SumTableNorm)
Yearly Class Yearly ClassOW Yearly All Weekly Class Weekly ClassOW Weekly All Daily Class Daily ClassOW Daily All
____________ ______________ __________ ____________ ______________ __________ ___________ _____________ _________
Mu 169.10 171.05 195.90 136.84 137.44 149.52 115.97 116.20 122.82
Sigma 15.07 15.94 21.92 16.41 16.73 21.66 18.50 18.71 23.18
COV (%) 8.91 9.32 11.19 11.99 12.17 14.49 15.95 16.10 18.88
95th % 195.27 200.74 235.65 164.12 165.36 186.53 148.14 148.84 163.24
Dist 95 193.89 197.27 231.96 163.84 164.96 185.14 146.39 146.98 160.95
AlphaQ 0.49 0.50 0.60 0.44 0.45 0.52 0.42 0.42 0.48
disp(SumTableLogNorm)
Yearly Class Yearly ClassOW Yearly All Weekly Class Weekly ClassOW Weekly All Daily Class Daily ClassOW Daily All
____________ ______________ __________ ____________ ______________ __________ ___________ _____________ _________
Lambda 5.13 5.14 5.27 4.91 4.92 5.00 4.74 4.74 4.79
Zeta 0.09 0.09 0.11 0.12 0.12 0.14 0.16 0.16 0.19
95th % 195.27 200.74 235.65 164.12 165.36 186.53 148.14 148.84 163.24
Dist 95 195.24 198.44 234.26 165.53 166.67 187.52 149.53 150.13 164.83
AlphaQN 0.49 0.50 0.60 0.44 0.45 0.52 0.42 0.42 0.48
AlphaQLN 0.50 0.51 0.62 0.48 0.48 0.57 0.48 0.48 0.57
disp(SumTableLogNormComp)
Yearly Class Yearly ClassOW Yearly All W2Y Class W2Y ClassOW W2Y All D2Y Class D2Y ClassOW D2Y All
____________ ______________ __________ _________ ___________ _______ _________ ___________ _______
Lambda 5.13 5.14 5.27 5.18 5.19 5.32 5.20 5.20 5.33
Zeta 0.09 0.09 0.11 0.06 0.06 0.07 0.07 0.07 0.08
95th % 195.27 200.74 235.65 195.27 200.74 235.65 195.27 200.74 235.65
Dist 95 195.24 198.44 234.26 195.40 197.20 228.89 201.48 202.78 233.61
AlphaQLN Est 0.50 0.51 0.62 0.48 0.48 0.57 0.50 0.50 0.59
figure('Position',[0 0 1500 400]);
for i = 1:length(ClassType)
[MaxECDF, MaxECDFRank] = ecdf(Max.(Class).(BlockM).Max/2); MaxECDFRank = MaxECDFRank'; MaxECDF(1) = []; MaxECDFRank(1) = [];
scatter(norminv((1:length(MaxECDFRank))/(length(MaxECDFRank) + 1)),log(MaxECDFRank),7,C(j,:),'filled','DisplayName','Max Data');
mdl = fitlm(norminv((1:length(MaxECDFRank))/(length(MaxECDFRank) + 1)),log(MaxECDFRank),'linear');
plot(norminv((1:length(MaxECDFRank))/(length(MaxECDFRank) + 1)),mdl.Fitted,'-','Color',C(j,:),'DisplayName',['Fitted ' num2str(mdl.Rsquared.Ordinary,3)]);
%text(1,y1(1)+(y1(2)-y1(1))/j,['\lambda = ' sprintf('%.2f \n',mdl.Coefficients.Estimate(1)) '\zeta = ' sprintf('%.2f \n',mdl.Coefficients.Estimate(2)) sprintf('R^2: %.1f%%',mdl.Rsquared.Ordinary*100)])
text(1,y1(1)+(y1(2)-y1(1))*(j/6),sprintf('R^2: %.1f%%',mdl.Rsquared.Ordinary*100),"Color",C(j,:))
ylabel('log[ Total Tandem Load (kN) /2 ]')
xlabel('Standard Normal Percentile')
title(['Maximum Tandem Axles ' Class])
sgtitle('LogNormal Probability Paper','fontweight','bold','fontsize',12);
% Try with Gumbel Probability Paper
% for i = 1:length(ClassType)
% figure('Position',[0 0 1500 400]);
% [MaxECDF, MaxECDFRank] = ecdf(Max.(Class).(BlockM).Max/2); MaxECDFRank = MaxECDFRank';
% scatter(MaxECDFRank,-log(-log(MaxECDF)),7,'k','filled','DisplayName','Max Data');
% ylabel('-log(-log(Probability of non-exceedance))')
% xlabel('Total Tandem Load (kN) /2')
% legend('location','best')
% title(['Maximum Tandem Axles ' BlockM])
% sgtitle(['Gumbel Probability Paper - ' Class ' Axles'],'fontweight','bold','fontsize',12);