LazStats: Refactor SensUnit. Add pdf help to chm.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7404 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-04-25 21:13:49 +00:00
parent 71fb8c7899
commit 0e48719e6b
4 changed files with 514 additions and 531 deletions

View File

@ -182,6 +182,7 @@ object SensForm: TSensForm
Constraints.MinHeight = 200
ItemHeight = 0
MultiSelect = True
OnSelectionChange = VarListSelectionChange
TabOrder = 4
end
object InBtn: TBitBtn
@ -257,81 +258,64 @@ object SensForm: TSensForm
BorderSpacing.Top = 2
BorderSpacing.Right = 8
ItemHeight = 0
MultiSelect = True
OnSelectionChange = VarListSelectionChange
TabOrder = 8
end
object CancelBtn: TButton
object ResetBtn: TButton
AnchorSideRight.Control = ComputeBtn
AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom
Left = 243
Height = 25
Top = 546
Width = 62
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Left = 12
BorderSpacing.Top = 8
BorderSpacing.Right = 12
BorderSpacing.Bottom = 8
Cancel = True
Caption = 'Cancel'
ModalResult = 2
TabOrder = 10
end
object ResetBtn: TButton
AnchorSideRight.Control = CancelBtn
AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom
Left = 177
Left = 269
Height = 25
Top = 546
Width = 54
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Left = 12
BorderSpacing.Left = 8
BorderSpacing.Top = 8
BorderSpacing.Right = 12
BorderSpacing.Right = 8
BorderSpacing.Bottom = 8
Caption = 'Reset'
OnClick = ResetBtnClick
TabOrder = 9
end
object ComputeBtn: TButton
AnchorSideRight.Control = ReturnBtn
AnchorSideRight.Control = CloseBtn
AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom
Left = 317
Left = 331
Height = 25
Top = 546
Width = 76
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Left = 12
BorderSpacing.Left = 8
BorderSpacing.Top = 8
BorderSpacing.Right = 12
BorderSpacing.Right = 8
BorderSpacing.Bottom = 8
Caption = 'Compute'
OnClick = ComputeBtnClick
TabOrder = 11
TabOrder = 10
end
object ReturnBtn: TButton
object CloseBtn: TButton
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom
Left = 405
Left = 415
Height = 25
Top = 546
Width = 61
Width = 55
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Left = 12
BorderSpacing.Left = 8
BorderSpacing.Top = 8
BorderSpacing.Right = 12
BorderSpacing.Right = 8
BorderSpacing.Bottom = 8
Caption = 'Return'
ModalResult = 1
TabOrder = 12
Caption = 'Close'
ModalResult = 11
TabOrder = 11
end
object Memo1: TLabel
AnchorSideLeft.Control = Owner
@ -354,7 +338,7 @@ object SensForm: TSensForm
AnchorSideLeft.Control = Owner
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = ReturnBtn
AnchorSideBottom.Control = CloseBtn
Left = 0
Height = 8
Top = 530

View File

@ -1,3 +1,7 @@
// File for testing: boltsize.laz, use BoltLngth variable
// NOTE: THE OUTPUT DOES NOT EXACTLY MATCH THAT OF THE PDF DOCUMENTATION !!!!
unit SensUnit;
{$mode objfpc}{$H+}
@ -18,11 +22,10 @@ type
AllBtn: TBitBtn;
AlphaEdit: TEdit;
Bevel1: TBevel;
CancelBtn: TButton;
Memo1: TLabel;
ResetBtn: TButton;
ComputeBtn: TButton;
ReturnBtn: TButton;
CloseBtn: TButton;
InBtn: TBitBtn;
Label1: TLabel;
Label2: TLabel;
@ -47,9 +50,11 @@ type
procedure InBtnClick(Sender: TObject);
procedure OutBtnClick(Sender: TObject);
procedure ResetBtnClick(Sender: TObject);
procedure VarListSelectionChange(Sender: TObject; User: boolean);
private
{ private declarations }
FAutoSized: Boolean;
procedure UpdateBtnStates;
public
{ public declarations }
end;
@ -60,93 +65,101 @@ var
implementation
uses
Math;
Math, Utils;
{ TSensForm }
procedure TSensForm.ResetBtnClick(Sender: TObject);
VAR i : integer;
var
i: integer;
begin
AlphaEdit.Text := '0.05';
AlphaEdit.Text := FormatFloat('0.00', DEFAULT_ALPHA_LEVEL);
StandardizeChk.Checked := false;
PlotChk.Checked := false;
SlopesChk.Checked := false;
InBtn.Enabled := true;
OutBtn.Enabled := false;
AvgSlopeChk.Checked := false;
SelectedList.Clear;
VarList.Clear;
for i := 1 to NoVariables do VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]);
for i := 1 to NoVariables do
VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]);
UpdateBtnStates;
end;
procedure TSensForm.InBtnClick(Sender: TObject);
VAR index, i : integer;
var
i: integer;
begin
index := VarList.Items.Count;
i := 0;
while i < index do
while i < VarList.Items.Count do
begin
if (VarList.Selected[i]) then
if VarList.Selected[i] then
begin
SelectedList.Items.Add(VarList.Items.Strings[i]);
SelectedList.Items.Add(VarList.Items[i]);
VarList.Items.Delete(i);
index := index - 1;
i := 0;
end
else i := i + 1;
end else
i := i + 1;
end;
OutBtn.Enabled := true;
UpdateBtnStates;
end;
procedure TSensForm.AllBtnClick(Sender: TObject);
VAR count, i : integer;
var
i: integer;
begin
count := VarList.Items.Count;
if count <= 0 then exit;
for i := 0 to VarList.Items.Count-1 do
SelectedList.Items.Add(VarList.Items.Strings[i]);
SelectedList.Items.Add(VarList.Items[i]);
VarList.Clear;
OutBtn.Enabled := true;
InBtn.Enabled := false;
UpdateBtnStates;
end;
procedure TSensForm.ComputeBtnClick(Sender: TObject);
VAR
NoVars, noselected, count, half, q, tp, low, hi, col : integer;
Values, Slopes, AvgSlopes : DblDyneMat;
RankedQ, Sorted : DblDyneVec;
RowLabels, ColLabels, RankLabels : StrDyneVec;
selected : IntDyneVec;
temp, MedianSlope, MannKendall, Z, C, M1, M2, Alpha, mean, stddev : double;
cellstring, outline : string;
i, j, k, no2do : integer;
Standardize, Plot, SlopePlot, AvgSlope : boolean;
var
//NoVars,
noselected, count, half, q, tp, low, hi, col: integer;
Values, Slopes, AvgSlopes: DblDyneMat;
RankedQ, Sorted: DblDyneVec;
RowLabels, ColLabels, RankLabels: StrDyneVec;
selected: IntDyneVec;
MedianSlope, MannKendall, Z, C, M1, M2, Alpha, mean, stddev: double;
cellstring, outline: string;
i, j, k, no2do: integer;
Standardize, Plot, SlopePlot, AvgSlope: boolean;
lReport: TStrings;
begin
Standardize := false;
Plot := false;
SlopePlot := false;
AvgSlope := false;
if StandardizeChk.Checked then Standardize := true;
if PlotChk.Checked then Plot := true;
if SlopesChk.Checked then SlopePlot := true;
if AvgSlopeChk.Checked then AvgSlope := true;
Alpha := 1.0 - StrToFloat(AlphaEdit.Text);
noselected := SelectedList.Items.Count;
NoSelected := SelectedList.Items.Count;
if noselected = 0 then
begin
ShowMessage('ERROR! First select variables to analyze.');
MessageDlg('First select variables to analyze.', mtError, [mbOk], 0);
exit;
end;
SetLength(RowLabels,NoCases);
SetLength(ColLabels,NoCases);
SetLength(selected,noselected);
SetLength(Values,NoCases,noselected+1);
SetLength(Slopes,NoCases,NoCases);
SetLength(RankedQ,NoVars); // !!!!!!!!!!!!!!!!!!! NoVars is not initialized !!!!!!!!!!!!!!!!!!!!!!
SetLength(Sorted,NoCases);
SetLength(AvgSlopes,NoCases,NoCases);
if AlphaEdit.Text = '' then begin
AlphaEdit.SetFocus;
MessageDlg('Input required.', mtError, [mbOk], 0);
exit;
end;
if not TryStrToFloat(AlphaEdit.Text, Alpha) or (Alpha <= 0) or (Alpha >= 1) then
begin
AlphaEdit.SetFocus;
MessageDlg('Numeric value required in range > 0 and < 1.', mtError, [mbOk], 0);
exit;
end;
Alpha := 1.0 - Alpha;
Standardize := StandardizeChk.Checked;
Plot := PlotChk.Checked;
SlopePlot := SlopesChk.Checked;
AvgSlope := AvgSlopeChk.Checked;
SetLength(RowLabels, NoCases);
SetLength(ColLabels, NoCases);
SetLength(selected, noselected);
SetLength(Values,NoCases, noselected+1);
SetLength(Slopes,NoCases, NoCases);
//SetLength(RankedQ, NoVars); // !!!!!!!!!!!!!!!!!!! NoVars is not initialized !!!!!!!!!!!!!!!!!!!!!!
SetLength(Sorted, NoCases);
SetLength(AvgSlopes, NoCases, NoCases);
for i := 0 to NoCases-1 do
begin
@ -156,43 +169,48 @@ begin
end;
// get selected variables
for i := 1 to noselected do
for i := 0 to noselected-1 do
begin
cellstring := SelectedList.Items.Strings[i-1];
cellstring := SelectedList.Items.Strings[i];
for j := 1 to NoVariables do
if cellstring = OS3MainFrm.DataGrid.Cells[j,0] then
selected[i-1] := j;
selected[i] := j;
end;
OutputFrm.RichEdit.Clear;
OutputFrm.RichEdit.Lines.Add('Sens Detection and Estimation of Trends');
outline := format('Number of data points = %d, Confidence Interval = %4.2f',
[NoCases,Alpha]);
OutputFrm.RichEdit.Lines.Add(outline);
OutputFrm.RichEdit.Lines.Add('');
lReport := TStringList.Create;
try
lReport.Add('SENS DETECTION AND ESTIMATION OF TRENDS');
lReport.Add('Number of data points: %4d', [NoCases]);
lReport.Add('Confidence Interval: %4.2f', [Alpha]);
lReport.Add('');
//Get the data
if AvgSlope then for i := 0 to NoCases-1 do Values[i,noselected] := 0.0;
if AvgSlope then
for i := 0 to NoCases-1 do
Values[i, noselected] := 0.0;
for j := 0 to noselected-1 do
begin
col := selected[j];
for i := 1 to NoCases do
begin
Values[i-1,j] := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col,i])));
if AvgSlope then Values[i-1,noselected] := Values[i-1,noselected] +
Values[i-1,j];
// Values[i-1, j] := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col, i]))); // wp: why round?
Values[i-1, j] := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col, i]));
if AvgSlope then
Values[i-1, noselected] := Values[i-1, noselected] + Values[i-1, j];
end;
end;
if PrtDataChk.Checked then
begin
outline:= 'CASE';
MAT_PRINT(Values,NoCases,noselected,outline,RowLabels,ColLabels,NoCases);
OutputFrm.ShowModal;
outline := 'CASE';
MatPrint(Values, NoCases, noselected, outline, RowLabels, ColLabels, NoCases, lReport);
lReport.Add(DIVIDER);
lReport.Add('');
end;
// standardize if more than one variable and standardization elected
if (noselected > 1) and (standardize = true) then
if (noselected > 1) and standardize then
begin
for j := 0 to noselected-1 do
begin
@ -201,108 +219,100 @@ begin
for i := 0 to NoCases-1 do
begin
mean := mean + Values[i,j];
stddev := stddev + (Values[i,j] * Values[i,j]);
stddev := stddev + sqr(Values[i,j]);
end;
stddev := stddev - (mean * mean) / NoCases;
stddev := stddev - sqr(mean) / NoCases;
stddev := stddev / (NoCases - 1);
stddev := sqrt(stddev);
mean := mean / NoCases;
for i := 0 to NoCases-1 do
Values[i,j] := (Values[i,j] - mean)/ stddev;
Values[i,j] := (Values[i,j] - mean) / stddev;
col := selected[j];
outline := format('Variable = %s, mean = %8.3f, standard deviation = %8.3f',
[OS3MainFrm.DataGrid.Cells[col,0],mean,stddev]);
OutputFrm.RichEdit.Lines.Add(outline);
lReport.Add('Variable: %s, mean: %8.3f, standard deviation: %8.3f', [OS3MainFrm.DataGrid.Cells[col,0], mean, stddev]);
end;
end;
// average the values if elected
if AvgSlope then for i := 0 to NoCases - 1 do Values[i,noselected] :=
Values[i,noselected] / noselected;
if AvgSlope then
for i := 0 to NoCases - 1 do
Values[i, noselected] := Values[i,noselected] / noselected;
// get interval slopes
no2do := noselected;
if AvgSlope then no2do := no2do + 1;
if AvgSlope then
no2do := no2do + 1;
for j := 0 to no2do - 1 do
begin
if j < noselected then
begin
col := selected[j];
cellstring := OS3MainFrm.DataGrid.Cells[col,0];
end
else
end else
begin
col := 0;
cellstring := 'Combined Scores';
end;
for i := 0 to NoCases-2 do
begin
for k := i + 1 to NoCases-1 do
Slopes[i,k] := (Values[k,j] - Values[i,j]) / (k-i);
end;
if PrtSlopesChk.Checked then
begin
outline := 'CASE';
MAT_PRINT(Slopes,NoCases,NoCases,outline,RowLabels,ColLabels,NoCases);
MatPrint(Slopes, NoCases, NoCases, outline, RowLabels, ColLabels, NoCases, lReport);
end;
// get ranked slopes and median estimator
SetLength(RankedQ, 500); // wp: overcome initialization issue with NoVars.
count := 0;
for i := 0 to NoCases-2 do
begin
for k := i+1 to NoCases-1 do
begin
RankedQ[count] := Slopes[i,k];
count := count + 1;
if count = Length(RankedQ) then
SetLength(RankedQ, Length(RankedQ) + 500);
end;
end;
SetLength(RankedQ, count);
//sort into ascending order
for i := 0 to count - 2 do
begin
for k := i + 1 to count-1 do
begin
if RankedQ[i] > RankedQ[k] then
begin
temp := RankedQ[i];
RankedQ[i] := RankedQ[k];
RankedQ[k] := temp;
end;
end;
end;
Exchange(RankedQ[i], RankedQ[k]);
if PrtRanksChk.Checked then
begin
SetLength(RankLabels,count);
for k := 0 to count-1 do RankLabels[k] := IntToStr(k+1);
OutputFrm.RichEdit.Lines.Add('Ranked Slopes');
SetLength(RankLabels, count);
for k := 0 to count-1 do
RankLabels[k] := IntToStr(k+1);
lReport.Add('Ranked Slopes');
for i := 0 to count-1 do
begin
outline := format('Label = %s, Ranked Q = %8.3f',
[RankLabels[i],RankedQ[i]]);
OutputFrm.RichEdit.Lines.Add(outline);
end;
OutputFrm.ShowModal;
lReport.Add('Label: %s, Ranked Q: %8.3f', [RankLabels[i], RankedQ[i]]);
// lReport.Add('Label: %d, Ranked Q: %8.3f', [k+1, RankedQ[i]]); <--- wp: test this. It should avoid using the RankLabela array
lReport.Add('');
lReport.Add(DIVIDER);
lReport.Add('');
RankLabels := nil;
end;
// get median slope
half := count div 2;
if (2 * half) < count then MedianSlope := RankedQ[half]
else MedianSlope := (RankedQ[half-1] + RankedQ[half]) / 2.0;
if (2 * half) < count then // wp: Isn't this the same as "odd(count)"?
MedianSlope := RankedQ[half]
else
MedianSlope := (RankedQ[half-1] + RankedQ[half]) / 2.0;
// get Mann-Kendall statistic based on tied values
for i := 0 to NoCases-1 do Sorted[i] := Values[i,j];
for i := 0 to NoCases-1 do
Sorted[i] := Values[i,j];
for i := 0 to NoCases-2 do
begin
for k := i+1 to NoCases-1 do
begin
if Sorted[i] > Sorted[k] then
begin
temp := Sorted[i];
Sorted[i] := Sorted[k];
Sorted[k] := temp;
end;
Exchange(Sorted[i], Sorted[k]);
end;
end;
@ -319,80 +329,61 @@ begin
begin
i := k-1;
break;
end
else tp := tp + 1;
end else
tp := tp + 1;
end; // next k
if tp > 1 then
begin
q := q + 1;
MannKendall := MannKendall + (tp * (tp-1) * (2 * tp + 5));
end;
end; // end next i
MannKendall := (NoCases * (NoCases-1) * (2 * NoCases + 5) -
MannKendall) / 18.0;
MannKendall := (NoCases * (NoCases-1) * (2 * NoCases + 5) - MannKendall) / 18.0;
Z := inversez(Alpha);
if MannKendall > 0 then
begin
C := Z * sqrt(MannKendall);
M1 := (count - C) / 2.0;
M2 := (count + C) / 2.0;
end
else begin
outline := format('Error: z = %8.3f, Mann-Kendall = %8.3f',
[Z,MannKendall]);
OutputFrm.RichEdit.Lines.Add(outline);
end;
end else
lReport.Add('Error: z: %8.3f, Mann-Kendall: %8.3f', [Z, MannKendall]);
// show results
if j < noselected then
begin
outline := format('Results for %s',[cellstring]);
OutputFrm.RichEdit.Lines.Add(outline);
end
lReport.Add('Results for %s', [cellstring])
else
OutputFrm.RichEdit.Lines.Add('Results for Averaged Values');
if (noselected > 1) and (Standardize = true) then
lReport.Add('Results for Averaged Values');
if (noselected > 1) and Standardize then
begin
mean := 0.0;
stddev := 0.0;
for i := 0 to NoCases-1 do
begin
mean := mean + Values[i,j];
stddev := stddev + (Values[i,j] * Values[i,j]);
stddev := stddev + sqr(Values[i,j]);
end;
stddev := stddev - (mean * mean) / NoCases;
stddev := stddev - sqr(mean) / NoCases;
stddev := stddev / (NoCases - 1);
stddev := sqrt(stddev);
mean := mean / NoCases;
outline := format('Mean = %8.3f, Standard Deviation = %8.3f',
[mean,stddev]);
OutputFrm.RichEdit.Lines.Add(outline);
lReport.Add('Mean: %8.3f, Standard Deviation = %8.3f', [mean, stddev]);
end;
outline := format('Median Slope for %d values = %8.3f',
[count,MedianSlope]);
OutputFrm.RichEdit.Lines.Add(outline);
outline := format('Mann-Kendall Variance statistic = %8.3f (%d ties)',
[MannKendall,q]);
OutputFrm.RichEdit.Lines.Add(outline);
outline := format('Ranks of the lower and upper confidence = %8.3f, %8.3f',
[M1, M2+1]);
OutputFrm.RichEdit.Lines.Add(outline);
lReport.Add('Median Slope for %d values: %8.3f', [count, MedianSlope]);
lReport.Add('Mann-Kendall Variance statistic: %8.3f (%d ties)', [MannKendall, q]);
lReport.Add('Ranks of the lower and upper confidence: %8.3f, %8.3f', [M1, M2+1]);
low := round(M1 - 1.0);
if ((M1-1) - low) > 0.5 then low := round(M1-1);
hi := round(M2);
if (M2 - hi) > 0.5 then hi := round(M2);
if (low > 0) or (hi <= count) then
begin
outline := format('Corresponding lower and upper slopes = %8.3f, %8.3f',
[RankedQ[low],RankedQ[hi]]);
OutputFrm.RichEdit.Lines.Add(outline);
end
else begin
outline := format('ERROR! low rank = %d, hi rank = %d',
[low, hi]);
OutputFrm.RichEdit.Lines.Add(outline);
end;
OutputFrm.RichEdit.Lines.Add('');
lReport.Add('Corresponding lower and upper slopes: %8.3f, %8.3f', [RankedQ[low], RankedQ[hi]])
else
lReport.Add('ERROR! low rank = %d, hi rank = %d', [low, hi]);
lReport.Add('');
// plot slopes if elected
if Plot then
@ -402,11 +393,13 @@ begin
GraphFrm.GraphType := 2;
GraphFrm.nosets := 1;
GraphFrm.nbars := NoCases;
GraphFrm.BackColor := clYellow;
GraphFrm.WallColor := clBlue;
GraphFrm.FloorColor := clGray;
if j < noselected then GraphFrm.Heading := OS3MainFrm.DataGrid.Cells[col,0]
else GraphFrm.Heading := 'Average Values';
GraphFrm.BackColor := GRAPH_BACK_COLOR;
GraphFrm.WallColor := GRAPH_WALL_COLOR;
GraphFrm.FloorColor := GRAPH_FLOOR_COLOR;
if j < noselected then
GraphFrm.Heading := OS3MainFrm.DataGrid.Cells[col,0]
else
GraphFrm.Heading := 'Average Values';
GraphFrm.barwideprop := 1.0;
GraphFrm.AutoScaled := true;
GraphFrm.ShowLeftWall := true;
@ -419,7 +412,9 @@ begin
GraphFrm.Ypoints[0,k] := Values[k,j];
GraphFrm.Xpoints[0,k] := k+1;
end;
GraphFrm.ShowModal;
if GraphFrm.ShowModal <> mrOK then
exit;
GraphFrm.Ypoints := nil;
GraphFrm.Xpoints := nil;
end;
@ -432,9 +427,9 @@ begin
GraphFrm.GraphType := 2;
GraphFrm.nosets := 1;
GraphFrm.nbars := count;
GraphFrm.BackColor := clYellow;
GraphFrm.WallColor := clBlue;
GraphFrm.FloorColor := clGray;
GraphFrm.BackColor := GRAPH_BACK_COLOR;
GraphFrm.WallColor := GRAPH_WALL_COLOR;
GraphFrm.FloorColor := GRAPH_FLOOR_COLOR;
GraphFrm.Heading := 'Ranked Slopes';
GraphFrm.barwideprop := 1.0;
GraphFrm.AutoScaled := true;
@ -448,34 +443,30 @@ begin
GraphFrm.Ypoints[0,k] := RankedQ[k];
GraphFrm.Xpoints[0,k] := k+1;
end;
GraphFrm.ShowModal;
if not GraphFrm.ShowModal = mrOK then
exit;
GraphFrm.Ypoints := nil;
GraphFrm.Xpoints := nil;
end;
OutputFrm.ShowModal;
OutputFrm.RichEdit.Clear;
lReport.Add('');
lReport.Add(DIVIDER);
lReport.Add('');
end; // next variable j
if AvgSlope then
begin
for i := 0 to NoCases-2 do
begin
for k := i + 1 to NoCases-1 do
begin
AvgSlopes[i,k] := AvgSlopes[i,k] + Slopes[i,k];
end;
end;
end;
// Average multiple measures
if AvgSlope then
begin
OutputFrm.RichEdit.Lines.Add('Results for Averaged Slopes');
lReport.Add('Results for Averaged Slopes');
for i := 0 to NoCases-2 do
begin
for k := i + 1 to NoCases-1 do
AvgSlopes[i,k] := AvgSlopes[i,k] / noselected;
end;
// get ranked slopes and median estimator
count := 0;
@ -488,21 +479,17 @@ begin
end;
end;
for i := 0 to Count-2 do
begin
for j := i + 1 to count - 1 do
begin
if RankedQ[i] > RankedQ[j] then
begin
temp := RankedQ[i];
RankedQ[i] := RankedQ[j];
RankedQ[j] := temp;
end;
end;
end;
Exchange(RankedQ[i], RankedQ[j]);
// get median slope
half := count div 2;
if (2 * half) < count then MedianSlope := RankedQ[half + 1]
else MedianSlope := (RankedQ[half] + RankedQ[half+1]) / 2.0;
if (2 * half) < count then // again: should be "odd(count)"
MedianSlope := RankedQ[half + 1]
else
MedianSlope := (RankedQ[half] + RankedQ[half+1]) / 2.0;
// get Mann-Kendall statistic based on tied values
MannKendall := 0.0;
q := 0;
@ -517,8 +504,8 @@ begin
begin
i := j - 1;
break;
end
else tp := tp + 1;
end else
tp := tp + 1;
end;
if tp > 1 then
begin
@ -529,36 +516,30 @@ begin
MannKendall := (NoCases * (NoCases-1) * (2 * NoCases + 5) - MannKendall) / 18.0;
Z := inversez(Alpha);
if MannKendall < 0.0 then
begin
outline := format('Error in calculating Mann-Kendall = %8.3f',
[MannKendall]);
ShowMessage(outline);
end;
if MannKendall > 0.0 then C := Z * sqrt(MannKendall)
else C := Z;
MessageDlg(Format('Error in calculating Mann-Kendall: %8.3f', [MannKendall]), mtError, [mbOK], 0);
if MannKendall > 0.0 then
C := Z * sqrt(MannKendall)
else
C := Z;
M1 := (count - C) / 2.0;
M2 := (count + C) / 2.0;
// Show results
outline := format('Median Slope for %d values = %8.3f for averaged measures',
[count,MedianSlope]);
OutputFrm.RichEdit.Lines.Add(outline);
outline := format('Mann-Kendall Variance statistic = %8.3f (%d ties observed)',
[MannKendall,q]);
OutputFrm.RichEdit.Lines.Add(outline);
outline := format('Ranks of the lower and upper confidence = (%8.3f, %8.3f)',
[M1, M2]);
OutputFrm.RichEdit.Lines.Add(outline);
lReport.Add('Median Slope for %d values: %8.3f for averaged measures', [count, MedianSlope]);
lReport.Add('Mann-Kendall Variance statistic: %8.3f (%d ties observed)', [MannKendall, q]);
lReport.Add('Ranks of the lower and upper confidence: (%8.3f, %8.3f)', [M1, M2]);
low := round(M1) - 1;
if ((M1-1) - low) > 0.5 then low := round(M1 - 1);
hi := round(M2);
if (M2 - hi) > 0.5 then hi := round(M2);
outline := format('Corresponding lower and upper slopes = (%8.3f, %8.3f)',
[RankedQ[low],RankedQ[hi]]);
OutputFrm.RichEdit.Lines.Add(outline);
lReport.Add('Corresponding lower and upper slopes: (%8.3f, %8.3f)', [RankedQ[low],RankedQ[hi]]);
end; // end if average slope
OutputFrm.ShowModal;
// cleanup
DisplayReport(lReport);
finally
lReport.Free;
AvgSlopes := nil;
Sorted := nil;
RankedQ := nil;
@ -567,6 +548,7 @@ begin
selected := nil;
ColLabels := nil;
RowLabels := nil;
end;
end;
procedure TSensForm.FormActivate(Sender: TObject);
@ -576,11 +558,10 @@ begin
if FAutoSized then
exit;
w := MaxValue([ResetBtn.Width, CancelBtn.Width, ComputeBtn.Width, ReturnBtn.Width]);
w := MaxValue([ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]);
ResetBtn.Constraints.MinWidth := w;
CancelBtn.Constraints.MinWidth := w;
ComputeBtn.Constraints.MinWidth := w;
ReturnBtn.Constraints.MinWidth := w;
CloseBtn.Constraints.MinWidth := w;
Constraints.MinWidth := Width;
Constraints.MinHeight := Height;
@ -591,20 +572,38 @@ end;
procedure TSensForm.FormCreate(Sender: TObject);
begin
Assert(OS3MainFrm <> nil);
if OutputFrm = nil then
Application.CreateForm(TOutputFrm, OutputFrm);
if GraphFrm = nil then
Application.CreateForm(TGraphFrm, GraphFrm);
end;
procedure TSensForm.OutBtnClick(Sender: TObject);
VAR index : integer;
var
i: integer;
begin
index := SelectedList.ItemIndex;
VarList.Items.Add(SelectedList.Items.Strings[index]);
SelectedList.Items.Delete(index);
InBtn.Enabled := true;
if SelectedList.Items.Count = 0 then OutBtn.Enabled := false;
i := 0;
while i < SelectedList.Items.Count do
begin
if SelectedList.Selected[i] then
begin
VarList.Items.Add(SelectedList.Items[i]);
SelectedList.Items.Delete(i);
i := 0;
end else
i := i + 1;
end;
UpdateBtnStates;
end;
procedure TSensForm.UpdateBtnStates;
begin
InBtn.Enabled := AnySelected(VarList);
OutBtn.Enabled := AnySelected(SelectedList);
AllBtn.Enabled := Varlist.Items.Count > 0;
end;
procedure TSensForm.VarListSelectionChange(Sender: TObject; User: boolean);
begin
UpdateBtnStates;
end;
initialization