// Data file for testing: anova2.laz // - Row, Col --> Fixed effect independent variables // - Cov1, Col2 --> Covariates (continuous) // - X --> Continuouse dependent variables // - Begin definition of an interaction, click Row, Col, end definition unit GLMUnit; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, MainUnit, MatrixLib, Globals, OutputUnit, FunctionsLib, DictionaryUnit, StdCtrls, Buttons, ExtCtrls, ContextHelpUnit; type { TGLMFrm } TGLMFrm = class(TForm) Bevel1: TBevel; Bevel2: TBevel; Bevel3: TBevel; HelpBtn: TButton; Memo2: TLabel; Panel1: TPanel; Panel10: TPanel; Panel11: TPanel; Panel12: TPanel; Panel13: TPanel; Panel14: TPanel; Panel2: TPanel; Panel3: TPanel; Panel4: TPanel; Panel5: TPanel; Panel6: TPanel; Panel7: TPanel; Panel8: TPanel; Panel9: TPanel; ShowDesignChk: TCheckBox; ContDepInBtn: TBitBtn; GroupBox2: TGroupBox; RndIndepOutBtn: TBitBtn; CovInBtn: TBitBtn; CovOutBtn: TBitBtn; ContDepOutBtn: TBitBtn; CatDepInBtn: TBitBtn; CatDepOutBtn: TBitBtn; ReptDepInBtn: TBitBtn; ReptDepOutBtn: TBitBtn; FixedIndepInBtn: TBitBtn; FixedIndepOutBtn: TBitBtn; RndIndepInBtn: TBitBtn; ContDepCode: TListBox; CatDepCode: TListBox; ReptDepCode: TListBox; FixedIndepCode: TListBox; RndIndepCode: TListBox; CovariateCode: TListBox; RepTrtCode: TListBox; ResetBtn: TButton; ComputeBtn: TButton; CloseBtn: TButton; DescChk: TCheckBox; CorsChk: TCheckBox; Label12: TLabel; IndOrderBox: TListBox; TypeGroup: TRadioGroup; ResidChk: TCheckBox; EndDefBtn: TButton; GroupBox1: TGroupBox; InterDefList: TListBox; Label11: TLabel; InteractList: TListBox; ShowModelBtn: TButton; DepContList: TListBox; ModelEdit: TEdit; FixedList: TListBox; Label10: TLabel; Label6: TLabel; DepCatList: TListBox; Label7: TLabel; Label8: TLabel; Label9: TLabel; CovariateList: TListBox; RepTrtList: TListBox; RandomList: TListBox; RepeatList: TListBox; VarList: TListBox; StartInterBtn: TButton; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel; Label5: TLabel; procedure CatDepInBtnClick(Sender: TObject); procedure CatDepOutBtnClick(Sender: TObject); procedure ComputeBtnClick(Sender: TObject); procedure ContDepCodeSelectionChange(Sender: TObject; User: boolean); procedure ContDepInBtnClick(Sender: TObject); procedure ContDepOutBtnClick(Sender: TObject); procedure CovariateListClick(Sender: TObject); procedure CovInBtnClick(Sender: TObject); procedure CovOutBtnClick(Sender: TObject); procedure EndDefBtnClick(Sender: TObject); procedure FixedIndepInBtnClick(Sender: TObject); procedure FixedIndepOutBtnClick(Sender: TObject); procedure FixedListClick(Sender: TObject); procedure FormActivate(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormShow(Sender: TObject); procedure HelpBtnClick(Sender: TObject); procedure Panel9Resize(Sender: TObject); procedure RandomListClick(Sender: TObject); procedure ReptDepInBtnClick(Sender: TObject); procedure ReptDepOutBtnClick(Sender: TObject); procedure RepTrtListClick(Sender: TObject); procedure ResetBtnClick(Sender: TObject); procedure RndIndepInBtnClick(Sender: TObject); procedure RndIndepOutBtnClick(Sender: TObject); procedure ShowModelBtnClick(Sender: TObject); procedure StartInterBtnClick(Sender: TObject); private { private declarations } IntDef : boolean; DefLine : integer; // number of interaction terms - 1 NoInterDefs : integer; // number of interactions in the model NContDep : integer; // no. of continuous dependent variables NCatDep : integer; // no. of categorical dependent variables NReptDep : integer; // no. of repeated dependent variables NFixedIndep : integer; // no. of fixed effect independent variables NRndIndep : integer; // no. of random effect independent variables NCovIndep : integer; // no. of covariate independent variables model : integer; // 1 if multreg, 2 if canonical novars : integer; // total no. of vectors in analysis grid totalobs : integer; // total no. of data grid observations gencount, oldcount : integer; // no. columns generated in datagrid ContDepID : IntDyneVec; // grid col. no.s of continuous dependent var.s CatDepID : IntDyneVec; // grid col. no.s of categorical dependent var.s ReptDepID : IntDyneVec; // grid col. no.s of repeated dep. variables FixedIndepID : IntDyneVec; // grid col. no.s of fixed independent var.s RndIndepID : IntDyneVec; // grid col. no.s of random independent var.s CovIndepID : IntDyneVec; // grid col. no.s of covariates DataGrid : DblDyneMat; // array for generated vectors and values GenLabels : StrDyneVec; // array of labels for data matrix ContDepPos : IntDyneVec; // datagrid position of continuous variables CatDepPos : IntDyneVec; // beginning datagrid position of categorical var. vectors ReptDepPos : IntDyneVec; // datagrid position of repeated variable ReptIndepPos : IntDyneVec; // datagrid pos. of subject vectors ReptTrtPos : IntDyneVec; // datagrid pos. of repeated treatment vectors FixedIndepPos : IntDyneVec; // datagrid position of first vector for cat indep. var. RndIndepPos : IntDyneVec; // datagrid position of first vector for rnd. indep. var. CovIndepPos : IntDyneVec; // datagrid positions of covariates InteractPos : IntDyneVec; // datagrid positions of interactions Labels : StrDyneVec; // labels for the analyses ColSelected : IntDyneVec; // datagrid columns of variables in the analysis NFixVecIndep : IntDyneVec; // no. of vectors for fixed independent vars. NRndVecIndep : IntDyneVec; // no. of vectors for random indep. vars. NFixVecDep : IntDyneVec; // no. of vectors for fixed dependent vars. NInteractVecs : IntDyneVec; // no. of vectors for each interaction OldR2 : double; // Previously obtained R^2 for stepwise addition R2 : double; // Squared mult. R obtained from RegAnal rmatrix : DblDyneMat; // correlation matrix indmatrix : DblDyneMat; // correlations among independent variable rxy : DblDyneVec; // correlations between dependent and independent var.s invmatrix : DblDyneMat; // inverse of independent correlations means : DblDyneVec; // means of variables Vars : DblDyneVec; // variances of variables StdDevs : DblDyneVec; // standard deviations of variables B : DblDyneVec; // raw regression coefficients Beta : DblDyneVec; // standardized regression coefficients workmat : DblDyneMat; // work matrix for inverse referenced at 1 (not zero) TypeISS : DblDyneVec; // Incremental SS TypeIISS : DblDyneVec; // Unique SS TypeIMS : DblDyneVec; // Incremental SS TypeIIMS : DblDyneVec; // Unique MS TypeIDF1 : DblDyneVec; // numerator d.f. for incremental ms TypeIIDF1 : DblDyneVec; // numerator d.f. for unique ms TypeIDF2 : DblDyneVec; // denominator d.f. for incremental ms TypeIIDF2 : DblDyneVec; // denominator d.f. for unique ms TypeIF : DblDyneVec; // F for incremental ms TypeIProb : DblDyneVec; // Probability of F for incremental ms TypeIIF : DblDyneVec; // F for unique MS TypeIIProb : DblDyneVec; // Probability for unique ms procedure AllocateIDMem; procedure GetIDs; function GetVarCount : integer; procedure AllocateGridMem; procedure DeallocateGridMem; procedure DeallocateIDMem; procedure DummyCodes(min, max: integer; const CodePattern: IntDyneMat); procedure EffectCodes(min, max: integer; const CodePattern: IntDyneMat); procedure OrthogCodes(min, max: integer; const CodePattern: IntDyneMat); procedure RegAnal(Nentered: integer; AReport: TStrings); procedure PartIEntry; procedure PartIIEntry; procedure ModelIAnalysis(AReport: TStrings); procedure ModelIIAnalysis(AReport: TStrings); procedure ModelIIIAnalysis(AReport: TStrings); function CntIntActVecs(linestr : string) : integer; procedure GenInterVecs(linestr : string); procedure CanCor(NLeft : integer; NRight : integer; GridPlace : IntDyneVec; AReport: TStrings); procedure UpdateBtnStates; public { public declarations } end; var GLMFrm: TGLMFrm; implementation uses Math, Utils; { TGLMFrm } procedure TGLMFrm.ResetBtnClick(Sender: TObject); VAR i : integer; begin VarList.Items.Clear; DepCatList.Items.Clear; DepContList.Items.Clear; RepeatList.Items.Clear; RepTrtList.Items.Clear; RepTrtCode.Items.Clear; FixedList.Items.Clear; RandomList.Items.Clear; CovariateList.Items.Clear; InterDefList.Items.Clear; InteractList.Items.Clear; ContDepCode.Items.Clear; CatDepCode.Items.Clear; ReptDepCode.Items.Clear; FixedIndepCode.Items.Clear; RndIndepCode.Items.Clear; CovariateCode.Items.Clear; IndOrderBox.Items.Clear; ModelEdit.Text := ''; NContDep := 0; NCatDep := 0; NReptDep := 0; NFixedIndep := 0; NRndIndep := 0; NCovIndep := 0; DescChk.Checked := false; CorsChk.Checked := false; ResidChk.Checked := false; TypeGroup.ItemIndex := 0; ContDepOutBtn.Enabled := false; CatDepOutBtn.Enabled := false; ReptDepOutBtn.Enabled := false; FixedIndepOutBtn.Enabled := false; RndIndepOutBtn.Enabled := false; CovOutBtn.Enabled := false; IntDef := false; DefLine := 0; NoInterDefs := 0; for i := 1 to NoVariables do VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]); end; procedure TGLMFrm.RndIndepInBtnClick(Sender: TObject); var i: integer; codestr: string; begin i := 0; while i < VarList.Items.Count do begin if VarList.Selected[i] then begin RandomList.Items.Add(VarList.Items[i]); VarList.Items.Delete(i); NRndIndep := NRndIndep + 1; codestr := Format('IR%d', [NRndIndep]); RndIndepCode.Items.Add(codestr); IndOrderBox.Items.Add(codestr); i := 0; end else i := i + 1; end; UpdateBtnStates; end; (* var index: integer; codestr: string; begin index := VarList.ItemIndex; if index > -1 then begin RandomList.Items.Add(VarList.Items[index]); VarList.Items.Delete(index); NRndIndep := NRndIndep + 1; codestr := format('IR%d',[NRndIndep]); RndIndepCode.Items.Add(codestr); IndOrderBox.Items.Add(codestr); end; end; *) procedure TGLMFrm.RndIndepOutBtnClick(Sender: TObject); var i, index: integer; cellstring: string; begin index := RandomList.ItemIndex; if index > -1 then begin VarList.Items.Add(RandomList.Items[index]); RandomList.Items.Delete(index); cellstring := RndIndepCode.Items[index]; RndIndepCode.Items.Delete(index); for i := IndOrderBox.Items.Count - 1 downto 0 do if cellstring = IndOrderBox.Items.Strings[i] then IndOrderBox.Items.Delete(i); NRndIndep := NRndIndep - 1; end; UpdateBtnStates; end; procedure TGLMFrm.ShowModelBtnClick(Sender: TObject); var i : integer; codestr : string; begin // add all dependent variable codes if NContDep > 0 then begin for i := 0 to NContDep - 1 do begin ModelEdit.Text := ModelEdit.Text + ContDepCode.Items.Strings[i]; if i < NContDep - 1 then ModelEdit.Text := ModelEdit.Text + ' + '; end; end; if NCatDep > 0 then begin if ModelEdit.Text <> '' then ModelEdit.Text := ModelEdit.Text + ' + '; for i := 0 to NCatDep - 1 do begin ModelEdit.Text := ModelEdit.Text + CatDepCode.Items.Strings[i]; if i < NCatDep - 1 then ModelEdit.Text := ModelEdit.Text + ' + '; end; end; if NReptDep > 0 then begin if ModelEdit.Text <> '' then ModelEdit.Text := ModelEdit.Text + ' + '; ModelEdit.Text := ModelEdit.Text + 'Rep'; end; // now add the independent variable codes ModelEdit.Text := ModelEdit.Text + ' = '; if NFixedIndep > 0 then begin for i := 0 to NFixedIndep - 1 do begin ModelEdit.Text := ModelEdit.Text + FixedIndepCode.Items.Strings[i]; if i < NFixedIndep - 1 then ModelEdit.Text := ModelEdit.Text + ' + '; end; end; if NRndIndep > 0 then begin if NFixedIndep > 0 then ModelEdit.Text := ModelEdit.Text + ' + '; for i := 0 to NRndIndep - 1 do begin ModelEdit.Text := ModelEdit.Text + RndIndepCode.Items.Strings[i]; if i < NRndIndep - 1 then ModelEdit.Text := ModelEdit.Text + ' + '; end; end; if NCovIndep > 0 then begin if (NFixedIndep > 0) or (NRndIndep > 0) then ModelEdit.Text := ModelEdit.Text + ' + '; for i := 0 to NCovIndep - 1 do begin ModelEdit.Text := ModelEdit.Text + CovariateCode.Items.Strings[i]; if i < NCovIndep - 1 then ModelEdit.Text := ModelEdit.Text + ' + '; end; end; // now add interactions if NoInterDefs > 0 then begin ModelEdit.Text := ModelEdit.Text + ' + '; for i := 0 to NoInterDefs - 1 do begin ModelEdit.Text := ModelEdit.Text + InterActList.Items.Strings[i]; if i < NoInterDefs - 1 then ModelEdit.Text := ModelEdit.Text + ' + '; end; end; // Now add person vectors if NReptDep > 0 then begin ModelEdit.Text := ModelEdit.Text + ' + '; for i := 0 to NReptDep - 1 do begin codestr := format('IP%d',[i+1]); ModelEdit.Text := ModelEdit.Text + codestr; if i < NReptDep - 1 then ModelEdit.Text := ModelEdit.Text + ' + '; end; end; // Now add repeated treatments if NReptDep > 0 then begin ModelEdit.Text := ModelEdit.Text + ' + '; for i := 0 to NReptDep - 1 do begin codestr := format('IR%d',[i+1]); ModelEdit.Text := ModelEdit.Text + codestr; if i < NReptDep - 1 then ModelEdit.Text := ModelEdit.Text + ' + '; end; end; end; procedure TGLMFrm.StartInterBtnClick(Sender: TObject); begin IntDef := true; end; procedure TGLMFrm.FormActivate(Sender: TObject); var w: Integer; begin w := MaxValue([HelpBtn.Width, ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]); HelpBtn.Constraints.MinWidth := w; ResetBtn.Constraints.MinWidth := w; ComputeBtn.Constraints.MinWidth := w; CloseBtn.Constraints.MinWidth := w; end; procedure TGLMFrm.FormCreate(Sender: TObject); begin Assert(OS3MainFrm <> nil); if DictionaryFrm = nil then Application.CreateForm(TDictionaryFrm, DictionaryFrm); end; procedure TGLMFrm.FormShow(Sender: TObject); begin ResetBtnClick(self); end; procedure TGLMFrm.HelpBtnClick(Sender: TObject); begin if ContextHelpForm = nil then Application.CreateForm(TContextHelpForm, ContextHelpForm); ContextHelpForm.HelpMessage((Sender as TButton).Tag); end; procedure TGLMFrm.RandomListClick(Sender: TObject); VAR index : integer; begin if IntDef then begin index := RandomList.ItemIndex; InterDefList.Items.Add(RndIndepCode.Items.Strings[index]); DefLine := DefLine + 1; // counter for number of terms - 1 end; end; procedure TGLMFrm.ReptDepInBtnClick(Sender: TObject); var i: integer; codestr: string; begin i := 0; while i < VarList.Items.Count do begin if VarList.Selected[i] then begin RepeatList.Items.Add(VarList.Items[i]); VarList.Items.Delete(i); NReptDep := NReptDep + 1; codestr := Format('DR%d', [NReptDep]); if NReptDep = 1 then begin ReptDepCode.Items.Add(codestr); codestr := Format('IP%d', [NReptDep]); IndOrderBox.Items.Add(codestr); codestr := Format('IR%d', [NReptDep]); IndOrderBox.Items.Add(codestr); RepTrtCode.Items.Add(codestr); codestr := Format('Rep.Trt.%d', [NReptDep]); RepTrtList.Items.Add(codestr); end; i := 0; end else i := i + 1; end; UpdateBtnStates; end; procedure TGLMFrm.ReptDepOutBtnClick(Sender: TObject); var index: integer; begin index := RepeatList.ItemIndex; if index > -1 then begin VarList.Items.Add(RepeatList.Items[index]); RepeatList.Items.Delete(index); ReptDepCode.Items.Delete(index); NReptDep := NReptDep - 1; end; UpdateBtnStates; end; procedure TGLMFrm.RepTrtListClick(Sender: TObject); VAR index : integer; begin if IntDef then begin index := RepTrtList.ItemIndex; InterDefList.Items.Add(RepTrtCode.Items.Strings[index]); DefLine := DefLine + 1; // counter for number of terms end; end; procedure TGLMFrm.ContDepInBtnClick(Sender: TObject); var index: integer; codestr: string; begin index := VarList.ItemIndex; if index > -1 then begin DepContList.Items.Add(VarList.Items[index]); VarList.Items.Delete(index); NContDep := NContDep + 1; codestr := Format('DC%d',[NContDep]); ContDepCode.Items.Add(codestr); end; UpdateBtnStates; end; procedure TGLMFrm.ContDepOutBtnClick(Sender: TObject); var index: integer; begin index := DepContList.ItemIndex; if index > -1 then begin VarList.Items.Add(DepContList.Items[index]); DepContList.Items.Delete(index); ContDepCode.Items.Delete(index); NContDep := NContDep - 1; end; UpdateBtnStates; end; procedure TGLMFrm.CatDepInBtnClick(Sender: TObject); var index: integer; codestr: string; begin index := VarList.ItemIndex; if index > -1 then begin DepCatList.Items.Add(VarList.Items[index]); VarList.Items.Delete(index); NCatDep := NCatDep + 1; codestr := format('DF%d',[NCatDep]); CatDepCode.Items.Add(codestr); end; UpdateBtnStates; end; procedure TGLMFrm.CatDepOutBtnClick(Sender: TObject); var index: integer; begin index := DepCatList.ItemIndex; if index > -1 then begin VarList.Items.Add(DepCatList.Items[index]); DepCatList.Items.Delete(index); CatDepCode.Items.Delete(index); NCatDep := NCatDep - 1; end; UpdateBtnStates; end; procedure TGLMFrm.ComputeBtnClick(Sender: TObject); var i, j: integer; // no. of variables in the analysis cellstring: string; lReport: TStrings; begin if (NContDep = 0) and (NCatDep = 0) and (NReptDep = 0) then begin ErrorMsg('No variables selected.'); exit; end; if (NContDep > 0) and (NReptDep > 0) then begin ErrorMsg('One cannot have both continuous and repeated dependent variables!'); exit; end; gencount := 0; // counter for generated variables totalobs := 0; // initialize total no. of observations in data grid AllocateIDMem; // get heap space for arrays GetIDs; // get var. no.s of dependent and independent variables novars := GetVarCount; // get total no. of variables to generate AllocateGridMem; // create data array for values and codes // Note, the Data Grid first subscript is row (subject) and second the var. if (NCatDep > 0) or (NContDep > 1) then model := 2 else model := 1; // use mult.reg for model 1, canonical reg. for model 2 if NReptDep > 0 then model := 3; // This procedure first creates the vectors of dependent variables then the // vectors for independent variables. A case no. is placed in the first // column of a data grid followed by the dependent variables and then the // independent variables. If multiple dependent variables are created, the // type of analysis is a canonical correlation analysis, otherwise a // multiple regression analysis. Analyses are performed to obtain both // Type I SS's and Type II SS's (stepwise addition and unique contribution) // PART I. ENTRY OF DEPENDENT VARIABLES (AND OBSERVATION NO.) // Place case labels in data grid and for repeated measures, spread out // the repeated measures over NoCases * No. repeated measures PartIEntry; // PART II. CREATION OF INDEPENDENT VARIABLE VECTORS // First, if there are repeated measures, generate (n - 1) person vectors PartIIEntry; lReport := TStringList.Create; try // Now, do the analyses case model of 1: ModelIAnalysis(lReport); // models with 1 dependent variable 2: ModelIIAnalysis(lReport); // models with 2 or more dependent var.s 3: ModelIIIAnalysis(lReport); // Repeated measures designs end; // Place generated data into the main form's grid if ShowDesignChk.Checked then begin if NoVariables < gencount then begin j := NoVariables; for i := j+1 to gencount do DictionaryFrm.NewVar(j); end; OS3MainFrm.DataGrid.RowCount := totalobs+1; for i := 1 to totalobs do for j := 1 to gencount do OS3MainFrm.DataGrid.Cells[j,i] := FloatToStr(DataGrid[i-1,j-1]); for i := 1 to gencount do begin OS3MainFrm.DataGrid.Cells[i,0] := GenLabels[i-1]; DictionaryFrm.Defaults(Self,i); DictionaryFrm.DictGrid.Cells[1,i] := GenLabels[i-1]; end; for i := 1 to totalobs do begin cellstring := format('CASE%d',[i]); OS3MainFrm.DataGrid.Cells[0,i] := cellstring; end; OS3MainFrm.NoCasesEdit.Text := IntToStr(totalobs); OS3MainFrm.NoVarsEdit.Text := IntToStr(gencount); NoVariables := gencount; NoCases := totalobs; OS3MainFrm.FileNameEdit.Text := ''; end; DisplayReport(lReport); finally lReport.Free; DeallocateGridMem; // free up heap allocated to data array DeallocateIDMem; // free up heap space end; end; procedure TGLMFrm.ContDepCodeSelectionChange(Sender: TObject; User: boolean); begin UpdateBtnStates; end; procedure TGLMFrm.CovariateListClick(Sender: TObject); var index: integer; begin if IntDef then begin index := CovariateList.ItemIndex; if index > -1 then begin InterDefList.Items.Add(CovariateCode.Items[index]); DefLine := DefLine + 1; // counter for number of terms - 1 end; end; end; procedure TGLMFrm.CovInBtnClick(Sender: TObject); var i: integer; codestr: string; begin i := 0; while i < VarList.Items.Count do begin if VarList.Selected[i] then begin CovariateList.Items.Add(VarList.Items[i]); VarList.Items.Delete(i); NCovIndep := NCovIndep + 1; codestr := Format('IC%d', [NCovIndep]); CovariateCode.Items.Add(codestr); IndOrderBox.Items.Add(codestr); i := 0; end else i := i + 1; end; UpdateBtnStates; end; { var index: integer; codestr: string; begin index := VarList.ItemIndex; if index > -1 then begin CovariateList.Items.Add(VarList.Items[index]); VarList.Items.Delete(index); NCovIndep := NCovIndep + 1; codestr := Format('IC%d', [NCovIndep]); CovariateCode.Items.Add(codestr); IndOrderBox.Items.Add(codestr); end; UpdateBtnStates; end; } procedure TGLMFrm.CovOutBtnClick(Sender: TObject); var i, index: integer; cellstring: string; begin index := CovariateList.ItemIndex; if index > -1 then begin VarList.Items.Add(CovariateList.Items[index]); CovariateList.Items.Delete(index); cellstring := CovariateCode.Items[index]; CovariateCode.Items.Delete(index); for i := IndOrderBox.Items.Count - 1 downto 0 do if cellstring = IndOrderBox.Items[i] then IndOrderBox.Items.Delete(i); NCovIndep := NCovIndep - 1; end; UpdateBtnStates; end; procedure TGLMFrm.EndDefBtnClick(Sender: TObject); var index: integer; nolines: integer; LineStr: string; begin LineStr := ''; nolines := InterDefList.Items.Count; if nolines > 0 then begin for index := 0 to nolines - 1 do begin LineStr := LineStr + InterDefList.Items.Strings[index]; if index < nolines - 1 then LineStr := LineStr + ' * '; end; InteractList.Items.Add(LineStr); IndOrderBox.Items.Add(LineStr); NoInterDefs := NoInterDefs + 1; end; InterDefList.Clear; end; procedure TGLMFrm.FixedIndepInBtnClick(Sender: TObject); var i: integer; codestr: string; begin i := 0; while i < VarList.Items.Count do begin if VarList.Selected[i] then begin FixedList.Items.Add(VarList.Items[i]); VarList.Items.Delete(i); NFixedIndep := NFixedIndep + 1; codestr := Format('IF%d', [NFixedIndep]); FixedIndepCode.Items.Add(codestr); IndOrderBox.Items.Add(codestr); i := 0; end else i := i + 1; end; UpdateBtnStates; end; procedure TGLMFrm.FixedIndepOutBtnClick(Sender: TObject); var i, index: integer; cellstring: string; begin index := FixedList.ItemIndex; if index > -1 then begin VarList.Items.Add(FixedList.Items[index]); FixedList.Items.Delete(index); cellstring := FixedIndepCode.Items[index]; FixedIndepCode.Items.Delete(index); NFixedIndep := NFixedIndep - 1; for i := IndOrderBox.Items.Count - 1 downto 0 do if IndOrderBox.Items.Strings[i] = cellstring then IndOrderBox.Items.Delete(i); end; UpdateBtnStates; end; procedure TGLMFrm.FixedListClick(Sender: TObject); var index: integer; begin if IntDef then begin index := FixedList.ItemIndex; if index > -1 then begin InterDefList.Items.Add(FixedIndepCode.Items[index]); DefLine := DefLine + 1; // counter for number of terms end; end; end; procedure TGLMFrm.AllocateIDMem; begin if NContDep > 0 then begin SetLength(ContDepID, NContDep); SetLength(ContDepPos, NContDep); end; if NCatDep > 0 then begin SetLength(CatDepID, NCatDep); SetLength(CatDepPos, NCatDep); SetLength(NFixVecDep, NCatDep); end; if NReptDep > 0 then begin SetLength(ReptDepID, NReptDep); SetLength(ReptDepPos, NReptDep); SetLength(ReptIndepPos, NoCases); SetLength(ReptTrtPos, NReptDep); end; if NFixedIndep > 0 then begin SetLength(FixedIndepID, NFixedIndep); SetLength(FixedIndepPos, NFixedIndep); SetLength(NFixVecIndep, NFixedIndep); end; if NRndIndep > 0 then begin SetLength(RndIndepID, NRndIndep); SetLength(RndIndepPos, NRndIndep); SetLength(NRndVecIndep, NRndIndep); end; if NCovIndep > 0 then begin SetLength(CovIndepID, NCovIndep); SetLength(CovIndepPos, NCovIndep); end; if NoInterDefs > 0 then begin SetLength(NInteractVecs, NoInterDefs); SetLength(InteractPos, NoInterDefs); end; end; procedure TGLMFrm.GetIDs; var cellstring: string; i, j: integer; begin if NContDep > 0 then begin for i := 0 to NContDep - 1 do begin cellstring := DepContList.Items[i]; for j := 1 to NoVariables do if cellstring = OS3MainFrm.DataGrid.Cells[j,0] then ContDepID[i] := j; end; end; if NCatDep > 0 then begin for i := 0 to NCatDep - 1 do begin cellstring := DepCatList.Items[i]; for j := 1 to NoVariables do if cellstring = OS3MainFrm.DataGrid.Cells[j,0] then CatDepID[i] := j; end; end; if NReptDep > 0 then begin for i := 0 to NReptDep - 1 do begin cellstring := RepeatList.Items[i]; for j := 1 to NoVariables do if cellstring = OS3MainFrm.DataGrid.Cells[j,0] then ReptDepID[i] := j; end; end; if NFixedIndep > 0 then begin for i := 0 to NFixedIndep - 1 do begin cellstring := FixedList.Items[i]; for j := 1 to NoVariables do if cellstring = OS3MainFrm.DataGrid.Cells[j,0] then FixedIndepID[i] := j; end; end; if NRndIndep > 0 then begin for i := 0 to NRndIndep - 1 do begin cellstring := RandomList.Items[i]; for j := 1 to NoVariables do if cellstring = OS3MainFrm.DataGrid.Cells[j,0] then RndIndepID[i] := j; end; end; if NCovIndep > 0 then begin for i := 0 to NCovIndep - 1 do begin cellstring := CovariateList.Items[i]; for j := 1 to NoVariables do if cellstring = OS3MainFrm.DataGrid.Cells[j,0] then CovIndepID[i] := j; end; end; end; function TGLMFrm.GetVarCount: integer; var count, i, j, col, nvectors: integer; min, max: integer; // use to get no. of coding vectors for categorical var.s group: integer; linestr: string; begin count := 1; // one column for case id's count := count + NContDep + NCovIndep; // sum of continuous variables if NReptDep > 0 then count := count + 1; // one col. for repeated dep. measure // plus person vectors for repeated measures (independent predictors) if NReptDep > 0 then count := count + (NoCases - 1); // person vectors if NReptDep > 0 then count := count + (NreptDep - 1); // repeated treatment vectors // calculate min and max for each var. to get no. of vectors if NCatDep > 0 then begin for i := 0 to NCatDep - 1 do begin col := CatDepID[i]; min := round(StrToFloat(OS3MainFrm.DataGrid.Cells[col,1])); max := min; for j := 1 to NoCases do begin group := round(StrToFLoat(OS3MainFrm.DataGrid.Cells[col,j])); if group < min then min := group; if group > max then max := group; end; count := count + (max - min); // 1 less than the no. of groups NFixVecDep[i] := count; end; end; // add no. of vectors to count if NFixedIndep > 0 then begin for i := 0 to NFixedIndep - 1 do begin col := FixedIndepID[i]; min := round(StrToFloat(OS3MainFrm.DataGrid.Cells[col,1])); max := min; for j := 1 to NoCases do begin group := round(StrToFloat(OS3MainFrm.DataGrid.Cells[col,j])); if group < min then min := group; if group > max then max := group; end; count := count + (max - min); // 1 less than the no. of groups NFixVecIndep[i] := max - min; end; end; // add no. of vectors to count if NRndIndep > 0 then begin for i := 0 to NRndIndep - 1 do begin col := RndIndepID[i]; min := round(StrToFloat(OS3MainFrm.DataGrid.Cells[col,1])); max := min; for j := 1 to NoCases do begin group := round(StrToFloat(OS3MainFrm.DataGrid.Cells[col,j])); if group < min then min := group; if group > max then max := group; end; count := count + (max - min); // 1 less than the no. of groups NRndVecIndep[i] := max - min; end; end; // get no. of vectors for each interaction if NoInterDefs > 0 then begin for i := 0 to NoInterDefs - 1 do begin linestr := InterActList.Items.Strings[i]; // parse the line for variable definitions and get no. of columns // and vectors for the products of these variables nvectors := CntIntActVecs(linestr); NInteractVecs[i] := nvectors; count := count + nvectors; end; end; Result := count; end; procedure TGLMFrm.AllocateGridMem; var norows: integer; begin if NReptDep > 0 then norows := NoCases * NReptDep else norows := NoCases; SetLength(DataGrid, norows+1, novars+4); // grid data for generated data SetLength(GenLabels, novars+4); // column labels of new data grid SetLength(Labels, novars+4); // labels of variables entered into analysis SetLength(ColSelected, novars+4); // datagrid columns selected for analysis end; procedure TGLMFrm.DeallocateGridMem; begin ColSelected := nil; Labels := nil; GenLabels := nil; DataGrid := nil; end; procedure TGLMFrm.DeallocateIDMem; begin InteractPos := nil; NInteractVecs := nil; CovIndepPos := nil; CovIndepID := nil; NRndVecIndep := nil; RndIndepPos := nil; RndIndepID := nil; NFixVecIndep := nil; FixedIndepPos := nil; FixedIndepID := nil; ReptTrtPos := nil; ReptIndepPos := nil; ReptDepPos := nil; ReptDepID := nil; NFixVecDep := nil; CatDepPos := nil; CatDepID := nil; ContDepPos := nil; ContDepID := nil; end; procedure TGLMFrm.DummyCodes(min, max: integer; const CodePattern: IntDyneMat); var ngrps: integer; vects: integer; i, j: integer; begin ngrps := max - min + 1; vects := ngrps - 1; for j := 1 to vects do for i := 1 to ngrps do if i = j then CodePattern[i,j] := 1 else CodePattern[i,j] := 0; end; procedure TGLMFrm.EffectCodes(min, max: integer; const CodePattern: IntDyneMat); var ngrps: integer; vects: integer; i, j: integer; begin ngrps := max - min + 1; vects := ngrps - 1; for i := 1 to ngrps do for j := 1 to vects do begin if i = j then CodePattern[i,j] := 1; if i = ngrps then CodePattern[i,j] := -1; if (i <> j) and (i <> ngrps) then CodePattern[i,j] := 0; end; end; procedure TGLMFrm.OrthogCodes(min, max: integer; const CodePattern: IntDyneMat); var ngrps: integer; vects: integer; i, j: integer; begin ngrps := max - min + 1; vects := ngrps - 1; for i := 1 to ngrps do for j := 1 to vects do begin if i <= j then CodePattern[i,j] := 1; if i-1 = j then CodePattern[i,j] := -j; if i > j+1 then CodePattern[i,j] := 0; end; end; procedure TGLMFrm.Panel9Resize(Sender: TObject); begin Bevel3.Constraints.MinHeight := Panel8.Height; end; procedure TGLMFrm.RegAnal(Nentered: integer; AReport: TStrings); var i, j, nvars, ncases: integer; title: string; begin nvars := Nentered; ncases := totalobs; SetLength(rmatrix, nvars+1, nvars+1); SetLength(indmatrix, nvars-1, nvars-1); SetLength(rxy, nvars); SetLength(invmatrix, nvars ,nvars); SetLength(B, nvars); SetLength(Beta, nvars); SetLength(means, nvars); SetLength(Vars, nvars); SetLength(StdDevs, nvars); SetLength(workmat, nvars, nvars); DynCorrelations(nvars, ColSelected, DataGrid, rmatrix, means, vars, StdDevs, ncases, 3); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); if DescChk.Checked then begin title := 'Means'; DynVectorPrint(means, Nentered, title, Labels, ncases, AReport); end; if CorsChk.Checked then begin title := 'Correlations'; MatPrint(rmatrix, Nentered, Nentered, title, Labels, Labels, ncases, AReport); end; for i := 1 to nvars - 1 do begin rxy[i-1] := rmatrix[i,0]; // r's with dependent var for j := 1 to nvars - 1 do begin indmatrix[i-1,j-1] := rmatrix[i,j]; // intercorr.s of indep. var.s workmat[i-1,j-1] := rmatrix[i,j]; // used to get inverse end; end; SVDinverse(workmat, nvars-1); // Copy inverse to zero indexed matrix for i := 1 to nvars-1 do for j := 1 to nvars-1 do invmatrix[i-1,j-1] := workmat[i-1,j-1]; title := 'inverse of indep. matrix'; // get betas and squared multiple correlation R2 := 0.0; for i := 1 to nvars-1 do begin Beta[i-1] := 0.0; for j := 1 to nvars-1 do Beta[i-1] := Beta[i-1] + invmatrix[i-1,j-1] * rxy[j-1]; R2 := R2 + Beta[i-1] * rxy[i-1]; end; // outline := format('Squared Multiple Correlation = %6.4f',[R2]); // OutputFrm.RichEdit.Lines.Add(outline); // title := 'Standardized regression coefficients'; // DynVectorPrint(Beta,Nentered-1,title,Labels,ncases); // get raw coefficients for i := 1 to nvars - 1 do begin if StdDevs[i] > 0.0 then B[i-1] := Beta[i-1] * (StdDevs[0] / StdDevs[i]) else B[i-1] := 0.0; end; // title := 'Raw regression coefficients'; // DynVectorPrint(B,Nentered-1,title,Labels,ncases); // OutputFrm.ShowModal; end; procedure TGLMFrm.PartIEntry; var i, j, k, vect : integer; min, max, group, ngrps : integer; CodePattern : IntDyneMat; cellstring: string; begin if NReptDep > 0 then // create observations for each replication of the N cases begin for i := 1 to NreptDep do begin ReptDepPos[i-1] := i; // datagrid pos. of a repeated measure for j := 1 to NoCases do begin DataGrid[totalobs,gencount] := j; // case no. in col. 0 k := ReptDepID[i-1]; DataGrid[totalobs,gencount+1] := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,j])); totalobs := totalobs + 1; end; end; // next i repeated measure gencount := gencount + 2; end else begin // no repeated measures - just need case numbers in data grid pos 0 for i := 1 to NoCases do DataGrid[i-1,gencount] := i; totalobs := NoCases; gencount := gencount + 1; end; GenLabels[0] := 'Obs.'; if NReptDep > 0 then GenLabels[1] := 'Repeated'; // Enter the continuous dependent variables into the data grid if NContDep > 0 then begin for j := 1 to NContDep do begin ContDepPos[j-1] := gencount; for i := 1 to NoCases do begin k := ContDepID[j-1]; DataGrid[i-1,gencount] := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i])); end; GenLabels[gencount] := ContDepCode.Items.Strings[j-1]; gencount := gencount + 1; end; end; // end if NContDep > 0 // Enter categorical dependent variables in the data grid if NCatDep > 0 then begin // get no. of categories - 1 for no of vectors to generate for each // categorical variable for j := 1 to NCatDep do begin CatDepPos[j-1] := gencount; k := CatDepID[j-1]; min := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,1]))); max := min; for i := 1 to NoCases do begin group := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i]))); if group > max then max := group; if group < min then min := group; end; ngrps := max-min+1; SetLength(CodePattern,ngrps+1,ngrps+1); if TypeGroup.ItemIndex = 0 then // dummy coding DummyCodes(min,max,CodePattern); if TypeGroup.ItemIndex = 1 then // effect coding EffectCodes(min,max,CodePattern); if TypeGroup.ItemIndex = 2 then // orthogonal coding OrthogCodes(min,max,CodePattern); // Now, generate vectors for the categorical variable j for vect := 1 to (max - min) do // vector no. begin for i := 1 to NoCases do begin group := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i]))); DataGrid[i-1,gencount + vect - 1] := CodePattern[group,vect]; end; cellstring := format('%s_%d',[CatDepCode.Items.Strings[j-1],vect]); GenLabels[gencount + vect - 1] := cellstring; end; gencount := gencount + (max - min); // new no. of variables end; // next categorical variable j end; // if no. of dependent categorical variables greater than zero codepattern := nil; end; procedure TGLMFrm.PartIIEntry; var i, j, k, vect, lastdep, row : integer; min, max, group, ngrps : integer; CodePattern : IntDyneMat; cellstring : string; value : double; begin lastdep := gencount; // datagrid position of last dependent variable // This section develops vectors for the independent variables. If there // are repeated measures, generate person vectors first. if NReptDep > 0 then begin min := 1; max := NoCases; ngrps := max-min+1; SetLength(CodePattern,ngrps+1,ngrps+1); if TypeGroup.ItemIndex = 0 then // dummy coding DummyCodes(min,max,CodePattern); if TypeGroup.ItemIndex = 1 then // effect coding EffectCodes(min,max,CodePattern); if TypeGroup.ItemIndex = 2 then // orthogonal coding OrthogCodes(min,max,CodePattern); for vect := 1 to (max - min) do // vector no. begin for i := 1 to totalobs do // NoCases begin group := round(DataGrid[i-1,0]); DataGrid[i-1,gencount + vect - 1] := CodePattern[group,vect]; end; ReptIndepPos[vect-1] := gencount + vect - 1; cellstring := Format('p%d', [vect]); GenLabels[gencount + vect - 1] := cellstring; end; gencount := gencount + (max - min); // new no. of variables end; // end generation of person codes // generate vectors for the repeated treatments if replications used if NReptDep > 0 then begin min := 1; max := NReptDep; ngrps := max-min+1; SetLength(CodePattern,ngrps+1,ngrps+1); if TypeGroup.ItemIndex = 0 then // dummy coding DummyCodes(min,max,CodePattern); if TypeGroup.ItemIndex = 1 then // effect coding EffectCodes(min,max,CodePattern); if TypeGroup.ItemIndex = 2 then // orthogonal coding OrthogCodes(min,max,CodePattern); for vect := 1 to (max - min) do // vector no. begin for i := 1 to totalobs do // NoCases begin group := ((i - 1) div NoCases) + 1; DataGrid[i-1,gencount + vect - 1] := CodePattern[group,vect]; end; ReptTrtPos[vect-1] := gencount + vect - 1; cellstring := format('IR_%d',[vect]); GenLabels[gencount + vect - 1] := cellstring; end; gencount := gencount + (max - min); // new no. of variables end; oldcount := gencount; // Next, add vectors for independent fixed categorical variables if NFixedIndep > 0 then begin // get no. of categories - 1 for no of vectors to generate for each // categorical variable for j := 1 to NFixedIndep do begin FixedIndepPos[j-1] := gencount; // first vector position in datagrid k := FixedIndepID[j-1]; min := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,1]))); max := min; for i := 1 to NoCases do begin group := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i]))); if group > max then max := group; if group < min then min := group; end; ngrps := max-min+1; SetLength(CodePattern,ngrps+1,ngrps+1); if TypeGroup.ItemIndex = 0 then // dummy coding DummyCodes(min,max,CodePattern); if TypeGroup.ItemIndex = 1 then // effect coding EffectCodes(min,max,CodePattern); if TypeGroup.ItemIndex = 2 then // orthogonal coding OrthogCodes(min,max,CodePattern); // Now, generate vectors for the categorical variable j for vect := 1 to (max - min) do // vector no. begin for i := 1 to NoCases do begin group := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i]))); DataGrid[i-1,gencount + vect - 1] := CodePattern[group,vect]; end; cellstring := format('%s_%d',[FixedIndepCode.Items.Strings[j-1],vect]); GenLabels[gencount + vect - 1] := cellstring; end; gencount := gencount + (max - min); // new no. of variables end; // next categorical variable j end; // end generation of fixed effect codes // Next, add vectors for independent random categorical variables oldcount := gencount; if NRndIndep > 0 then begin // get no. of categories - 1 for no of vectors to generate for each // categorical variable for j := 1 to NRndIndep do begin RndIndepPos[j-1] := gencount; // pos. of first vector in datagrid k := RndIndepID[j-1]; min := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,1]))); max := min; for i := 1 to NoCases do begin group := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i]))); if group > max then max := group; if group < min then min := group; end; ngrps := max-min+1; SetLength(CodePattern,ngrps+1,ngrps+1); if TypeGroup.ItemIndex = 0 then // dummy coding DummyCodes(min,max,CodePattern); if TypeGroup.ItemIndex = 1 then // effect coding EffectCodes(min,max,CodePattern); if TypeGroup.ItemIndex = 2 then // orthogonal coding OrthogCodes(min,max,CodePattern); // Now, generate vectors for the categorical variable j for vect := 1 to (max - min) do // vector no. begin for i := 1 to NoCases do begin group := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i]))); DataGrid[i-1,gencount + vect - 1] := CodePattern[group,vect]; end; cellstring := format('%s_%d',[RndIndepCode.Items.Strings[j-1],vect]); GenLabels[gencount + vect - 1] := cellstring; end; gencount := gencount + (max - min); // new no. of variables end; // next categorical variable j end; // end generation of random effect codes // Next, add covariates if NCovIndep > 0 then begin for j := 1 to NCovIndep do begin CovIndepPos[j-1] := gencount; for i := 1 to NoCases do begin k := CovIndepID[j-1]; DataGrid[i-1,gencount] := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i])); end; GenLabels[gencount] := CovariateCode.Items.Strings[j-1]; gencount := gencount + 1; end; end; // end generation of covariate codes // if repeated measures used, copy generated vectors for each replication if NReptDep > 0 then begin for j := 1 to NReptDep - 1 do begin for i := 1 to NoCases do begin for k := lastdep + (NoCases-1) +(NReptDep-1) + 1 to gencount do begin value := DataGrid[i-1,k-1]; row := (j * NoCases) + i - 1; DataGrid[row,k-1] := value; end; // next k column in data grid end; // next case end; // next repeated measure end; // if repeated measures used // Now generate product vectors for the interactions if NoInterDefs > 0 then begin for j := 0 to NoInterDefs - 1 do begin // parse an interaction line into components (abbreviations) and // get product of vectors corresponding to each InteractPos[j] := gencount; cellstring := InteractList.Items.Strings[j]; GenInterVecs(cellstring); gencount := gencount + NInteractVecs[j]; end; end; // end generation of interaction codes codepattern := nil; end; procedure TGLMFrm.ModelIAnalysis(AReport: TStrings); var block, i, j, k, NEntered, index, noblocks, priorentered : integer; cellstring : string; labelstr : string; R, R2Increment, SSx, sum, constant, FullR2 : double; df1, df2, F, FProbF, StdErrB, PredSS, PredMS : double; SSt, VarEst, SSres, StdErrEst, AdjR2 : double; begin NEntered := 0; priorentered := 0; OldR2 := 0; // enter the dependent variable first if NContDep > 0 then begin ColSelected[0] := ContDepPos[0]; Labels[0] := GenLabels[1]; end else begin ColSelected[0] := ReptDepPos[0]; Labels[0] := GenLabels[1]; end; NEntered := NEntered + 1; // Enter independent variables as indicated in indorderbox then interactions // until the total model is analyzed. Then delete each term to get a // restricted model and compare to the full model. noblocks := IndOrderBox.Items.Count; SetLength(TypeISS,noblocks); SetLength(TypeIISS,noblocks); SetLength(TypeIMS,noblocks); SetLength(TypeIIMS,noblocks); SetLength(TypeIDF1,noblocks); SetLength(TypeIDF2,noblocks); SetLength(TypeIIDF1,noblocks); SetLength(TypeIIDF2,noblocks); SetLength(TypeIF,noblocks); SetLength(TypeIProb,noblocks); SetLength(TypeIIF,noblocks); SetLength(TypeIIProb,noblocks); for block := 0 to noblocks - 1 do begin // get index of the abbreviation of term to enter and find corresponding // vector(s) to place in the equation cellstring := IndOrderBox.Items.Strings[block]; // check for covariates first if NCovIndep > 0 then begin for i := 0 to NCovIndep-1 do begin if cellstring = CovariateCode.Items.Strings[i] then // matched! begin index := i; // index of covariate code ColSelected[NEntered] := CovIndepPos[index]; labelstr := Format('%s', [CovariateCode.Items[index]]); Labels[NEntered] := labelstr; NEntered := NEntered + 1; break; end; end; end; // check for fixed effect variables next if NFixedIndep > 0 then begin for i := 0 to NFixedIndep-1 do begin if cellstring = FixedIndepCode.Items.Strings[i] then begin index := i; for j := 0 to NFixVecIndep[index]-1 do begin ColSelected[NEntered] := FixedIndepPos[index] + j; labelstr := Format('%s_%d',[FixedIndepCode.Items[index],j+1]); Labels[NEntered] := labelstr; NEntered := NEntered + 1; end; break; end; end; end; // Check for random effects variables next if NRndIndep > 0 then begin for i := 0 to NRndIndep-1 do begin if cellstring = RndIndepCode.Items.Strings[i] then begin index := i; for j := 0 to NRndVecIndep[index]-1 do begin ColSelected[NEntered] := RndIndepPos[index] + j; labelstr := Format('%s_%d',[RndIndepCode.Items[index],j+1]); Labels[NEntered] := labelstr; NEntered := NEntered + 1; end; break; end; end; end; // check for interactions next if NoInterDefs > 0 then begin for i := 0 to NoInterDefs-1 do begin if cellstring = InteractList.Items.Strings[i] then begin for j := 0 to NInteractVecs[i]-1 do begin ColSelected[NEntered] := InteractPos[i] + j; labelstr := Format('%s%d_%d',['IA',i+1,j+1]); Labels[NEntered] := labelstr; NEntered := NEntered + 1; end; break; end; end; end; // check for interaction variables // check for repeated measures variables (person codes) if NReptDep > 0 then begin // look for 'IP' in cellstring labelstr := copy(cellstring,0,2); if labelstr = 'IP' then // person vectors were generated begin for i := 0 to NoCases - 2 do begin ColSelected[NEntered] := ReptIndepPos[i]; Labels[NEntered] := GenLabels[ReptIndepPos[i]]; NEntered := NEntered + 1; end; end; end; // check for repeated treatments if NReptDep > 0 then begin // look for 'IR' in cellstring labelstr := copy(cellstring,0,2); if labelstr = 'IR' then // repeated treatment vectors were generated begin for i := 0 to NReptDep - 2 do begin ColSelected[NEntered] := ReptTrtPos[i]; Labels[NEntered] := GenLabels[ReptTrtPos[i]]; NEntered := NEntered + 1; end; end; end; RegAnal(NEntered, AReport); R := sqrt(R2); df1 := Nentered - 1; // no. of independent variables df2 := totalobs - df1 - 1; // N - no. independent - 1 SSt := (totalobs-1) * Vars[0]; SSres := SSt * (1.0 - R2); VarEst := SSres / df2; if (VarEst > 0.0) then StdErrEst := sqrt(VarEst) else begin ErrorMsg('Error in computing variance estimate.'); StdErrEst := 0.0; end; if (R2 < 1.0) and (df2 > 0.0) then F := (R2 / df1) / ((1.0-R2)/ df2) else F := 0.0; FProbF := probf(F,df1,df2); AdjR2 := 1.0 - (1.0 - R2) * (totalobs - 1) / df2; AReport.Add(' R R2 F Prob. > F DF1 DF2 '); AReport.Add('-------- ---------- ---------- ---------- ----- -----'); AReport.Add('%8.3f %10.3f %10.3f %10.3f %5.0f %5.0f', [R, R2, F, FProbF, df1, df2]); AReport.Add(''); AReport.Add('Adjusted R Squared: %10.3f', [AdjR2]); AReport.Add('Std. Error of Estimate: %10.3f', [StdErrEst]); AReport.Add(''); AReport.Add('Variable Beta B Std.Error t Prob. > t '); AReport.Add('---------- ---------- ---------- ---------- ---------- ----------'); df1 := 1.0; sum := 0.0; for i := 0 to Nentered - 2 do begin SSx := (totalobs-1) * Vars[i+1]; sum := sum + B[i] * means[i+1]; if invmatrix[i,i] > 1.0e-15 then begin StdErrB := VarEst / (SSx * (1.0 / invmatrix[i,i])); StdErrB := sqrt(StdErrB); if StdErrB > 0.0 then F := B[i] / StdErrB else F := 0.0; FProbF := probf(F*F,df1,df2); end else begin StdErrB := 0.0; F := 0.0; FProbF := 0.0; end; AReport.Add('%10s %10.3f %10.3f %10.3f %10.3f %10.3f', [Labels[i+1], Beta[i] ,B[i], StdErrB, F, FProbF]); end; AReport.Add(''); constant := means[0] - sum; AReport.Add('Constant: %10.3f', [constant]); // test increment in R2 for this block R2Increment := R2 - OldR2; if priorentered > 0 then df1 := (NEntered-1) - (priorentered-1) else df1 := NEntered - 1; df2 := totalobs - NEntered; TypeIDF1[block] := df1; TypeIDF2[block] := df2; TypeISS[block] := (R2 - OldR2) * SSt; TypeIMS[block] := TypeISS[block] / df1; F := ((R2 - OldR2)/ df1) / ((1.0 - R2) / df2); TypeIF[block] := F; FProbF := probf(F,df1,df2); TypeIProb[block] := FProbF; AReport.Add('Increment in Squared R: %10.3f', [R2Increment]); AReport.Add('F: %10.3f', [F]); AReport.Add(' with d.o.f. %10.0f and %.0f',[df1, df2]); // df is double! - why? AReport.Add(' and Prob > F %10.3f', [FProbF]); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); OldR2 := R2; priorentered := NEntered; // setup for next block analysis WorkMat := nil; StdDevs := nil; Vars := nil; means := nil; Beta := nil; B := nil; invmatrix := nil; rxy := nil; indmatrix := nil; rmatrix := nil; end; // next variable block // Next, obtain the unique (Type II values) by elimination of each block // from the full model and testing the decrement in R2 FullR2 := R2; // save previously obtained full model R2 for i := 0 to NoBlocks - 1 do begin NEntered := 0; // enter the dependent variable first if NContDep > 0 then begin ColSelected[0] := ContDepPos[0]; Labels[0] := GenLabels[1]; end else begin ColSelected[0] := ReptDepPos[0]; Labels[0] := GenLabels[1]; end; NEntered := NEntered + 1; for block := 0 to NoBlocks - 1 do begin if i = block then continue // delete this block else begin // enter the remaining blocks cellstring := IndOrderBox.Items.Strings[block]; // if a covariate, include it if NCovIndep > 0 then begin for j := 0 to NCovIndep-1 do begin if cellstring = CovariateCode.Items.Strings[j] then // matched! begin index := j; // index of covariate code ColSelected[NEntered] := CovIndepPos[index]; Labels[NEntered] := Format('%s', [CovariateCode.Items[index]]); NEntered := NEntered + 1; break; end; end; end; // check for fixed effect variables next if NFixedIndep > 0 then begin for j := 0 to NFixedIndep-1 do begin if cellstring = FixedIndepCode.Items.Strings[j] then begin index := j; for k := 0 to NFixVecIndep[index]-1 do begin ColSelected[NEntered] := FixedIndepPos[index] + k; Labels[NEntered] := Format('%s_%d', [FixedIndepCode.Items[index], k+1]); NEntered := NEntered + 1; end; break; end; end; end; // Check for random effects variables next if NRndIndep > 0 then begin for j := 0 to NRndIndep-1 do begin if cellstring = RndIndepCode.Items.Strings[j] then begin index := j; for k := 0 to NRndVecIndep[index]-1 do begin ColSelected[NEntered] := RndIndepPos[index] + k; Labels[NEntered] := Format('%s_%d', [RndIndepCode.Items[index], k+1]); NEntered := NEntered + 1; end; end; break; end; end; // check for interactions next if NoInterDefs > 0 then begin for j := 0 to NoInterDefs-1 do begin if cellstring = InteractList.Items.Strings[j] then begin for k := 0 to NInteractVecs[j]-1 do begin ColSelected[NEntered] := InteractPos[j] + k; Labels[NEntered] := Format('%s%d_%d', ['IA', j+1, k+1]); NEntered := NEntered + 1; end; break; end; // end if end; // next j end; // end if interdefs > 0 end; // entry of remaining blocks end; // enter next block not equal to block i RegAnal(NEntered, AReport); // compute restricted model if R2 > 0.0 then R := sqrt(R2) else R := 0.0; df1 := Nentered; // no. of independent variables df2 := totalobs - df1 - 1; // N - no. independent - 1 SSt := (totalobs-1) * Vars[0]; SSres := SSt * (1.0 - R2); VarEst := SSres / df2; if (VarEst > 0.0) then StdErrEst := sqrt(VarEst) else begin ErrorMsg('Error in computing variance estimate.'); StdErrEst := 0.0; end; if (R2 < 1.0) and (df2 > 0.0) then F := (R2 / df1) / ((1.0-R2)/ df2) else F := 0.0; FProbF := probf(F,df1,df2); AdjR2 := 1.0 - (1.0 - R2) * (totalobs - 1) / df2; AReport.Add(' R R2 F Prob. > F DF1 DF2 '); AReport.Add('-------- ---------- ---------- ---------- ----- -----'); AReport.Add('%8.3f %10.3f %10.3f %10.3f %5.0f %5.0f', [R, R2, F, FProbF, df1, df2]); AReport.Add(''); AReport.Add('Adjusted R Squared: %10.3f', [AdjR2]); AReport.Add('Std. Error of Estimate: %10.3f', [StdErrEst]); AReport.Add(''); AReport.Add('Variable Beta B Std.Error t Prob. > t '); AReport.Add('---------- ---------- ---------- ---------- ---------- ----------'); df1 := 1.0; sum := 0.0; for j := 0 to Nentered - 2 do begin SSx := (totalobs-1) * Vars[j+1]; sum := sum + B[j] * means[j+1]; if invmatrix[j,j] > 1.0e-18 then StdErrB := VarEst / (SSx * (1.0 / invmatrix[j,j])) else StdErrB := 0.0; if StdErrB > 0.0 then StdErrB := sqrt(StdErrB); if StdErrB > 0.0 then F := B[j] / StdErrB else F := 0.0; FProbF := probf(F*F,df1,df2); AReport.Add('%10s %10.3f %10.3f %10.3f %10.3f %10.3f', [Labels[j+1], Beta[j] ,B[j], StdErrB, F, FProbF]); end; AReport.Add(''); constant := means[0] - sum; AReport.Add('Constant: %10.3f', [constant]); // Now compute unique contribution of block left out (Type II) R2Increment := FullR2 - R2; df1 := (novars - 2) - (NEntered - 1); // k1 - k2 df2 := totalobs - (novars - 2) - 1; TypeIIDF1[i] := df1; TypeIIDF2[i] := df2; TypeIISS[i] := (FullR2 - R2) * SSt; TypeIIMS[i] := TypeIISS[i] / df1; F := ((FullR2 - R2)/ df1) / ((1.0 - FullR2) / df2); TypeIIF[i] := F; FProbF := probf(F,df1,df2); TypeIIProb[i] := FProbF; AReport.Add('Decrement in Squared R: %10.3f', [R2Increment]); AReport.Add('F: %10.3f', [F]); AReport.Add(' with d.o.f. %10.0f and %.0f',[df1, df2]); AReport.Add(' and Prob > F %10.3f', [FProbF]); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); // setup for next block analysis WorkMat := nil; StdDevs := nil; Vars := nil; means := nil; Beta := nil; B := nil; invmatrix := nil; rxy := nil; indmatrix := nil; rmatrix := nil; end; // next i block selected for elimination // Show summary table of Type I and Type II tests AReport.Add('SUMMARY TABLE FOR GLM EFFECTS'); AReport.Add(''); AReport.Add('Incremental Effects:'); AReport.Add('SOURCE DF1 DF2 SS MS F Prob > F'); AReport.Add('---------- ---- ---- ---------- ---------- ---------- --------'); for i := 0 to NoBlocks - 1 do begin cellstring := IndOrderBox.Items.Strings[i]; AReport.Add('%10s %4.0f %4.0f %10.3f %10.3f %10.3f %8.3f', [cellstring,TypeIDF1[i],TypeIDF2[i],TypeISS[i],TypeIMS[i],TypeIF[i],TypeIProb[i]] ); end; AReport.Add(''); AReport.Add('Unique Effects:'); AReport.Add('SOURCE DF1 DF2 SS MS F Prob > F'); AReport.Add('---------- ---- ---- ---------- ---------- ---------- --------'); for i := 0 to NoBlocks - 1 do begin cellstring := IndOrderBox.Items.Strings[i]; AReport.Add('%10s %4.0f %4.0f %10.3f %10.3f %10.3f %8.3f', [cellstring,TypeIIDF1[i],TypeIIDF2[i],TypeIISS[i],TypeIIMS[i],TypeIIF[i],TypeIIProb[i]] ); end; AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); // Show Anova Results for fixed and/or covariates if (NRndIndep = 0) and (NReptDep = 0) then // must be fixed and/or covariate only design begin if (NFixedIndep > 0) or (NCovIndep > 0) then // fixed effects begin df1 := novars - 2; // k1 (note: novars contains ID variable, dep, independents) PredSS := SSt * FullR2; PredMS := PredSS / df1; df2 := totalobs - df1 - 1; // residual df SSres := SSt * (1.0 - FullR2); VarEst := SSres / df2; // ms residual F := PredMS / VarEst; FProbF := probf(F,df1,df2); AReport.Add('SOURCE DF SS MS F Prob > F'); AReport.Add('-------------------- ---- ---------- ---------- ---------- --------'); AReport.Add('%20s %4.0f %10.3f %10.3f %10.3f %8.3f', ['Full Model', df1, PredSS, PredMS, F, FProbF]); for i := 0 to NoBlocks - 1 do begin F := TypeIMS[i] / VarEst; FProbF := probf(F,TypeIDF1[i],df2); cellstring := IndOrderBox.Items.Strings[i]; AReport.Add('%20s %4.0f %10.3f %10.3f %10.3f %8.3f', [cellstring, TypeIDF1[i], TypeISS[i], TypeIMS[i], F, FProbF]); end; AReport.Add('%20s %4.0f %10.3f %10.3f', ['Residual', df2, SSres, VarEst]); AReport.Add('%20s %4d %10.3f', ['Total', totalobs-1, SSt]); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); end; end; // Show Anova Results for random effects and/or covariates if (NFixedIndep = 0) and (NReptDep = 0) then // must be random only or covariate only design begin if (NRndIndep > 0) or (NCovIndep > 0) then // random and/or covariate effects begin df1 := novars - 2; // k1 (note: novars contains ID variable, dep, independents) PredSS := SSt * FullR2; PredMS := PredSS / df1; df2 := totalobs - df1 - 1; // residual df SSres := SSt * (1.0 - FullR2); VarEst := SSres / df2; // ms residual F := PredMS / VarEst; FProbF := probf(F,df1,df2); AReport.Add('SOURCE DF SS MS F Prob > F'); AReport.Add('-------------------- ---- ---------- ---------- ---------- --------'); AReport.Add('%20s %4.0f %10.3f %10.3f %10.3f %8.3f', ['Full Model', df1, PredSS, PredMS, F, FProbF]); for i := 0 to NoBlocks - 1 do begin F := TypeIMS[i] / VarEst; FProbF := probf(F,TypeIDF1[i],df2); AReport.Add('%20s %4.0f %10.3f %10.3f %10.3f %8.3f', [Labels[i+1], TypeIDF1[i], TypeISS[i], TypeIMS[i], F, FProbF]); end; AReport.Add('%20s %4.0f %10.3f %10.3f', ['Residual', df2, SSres, VarEst]); AReport.Add('%20s %4d %10.3f', ['Total', totalobs-1, SSt]); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); end; end; // show effects for repeated measures ANOVA (and covariates) if NReptDep > 0 then begin df1 := novars - 2; // k1 (note: novars contains ID variable, dep, independents) PredSS := SSt * FullR2; PredMS := PredSS / df1; df2 := totalobs - df1 - 1; // residual df SSres := SSt * (1.0 - FullR2); VarEst := SSres / df2; // ms residual F := PredMS / VarEst; FProbF := probf(F,df1,df2); AReport.Add('SOURCE DF SS MS F Prob > F'); AReport.Add('-------------------- ---- ---------- ---------- ---------- --------'); AReport.Add('%20s %4.0f %10.3f %10.3f %10.3f %8.3f', ['Full Model', df1, PredSS, PredMS, F, FProbF]); for i := 0 to NoBlocks - 1 do begin F := TypeIMS[i] / VarEst; FProbF := probf(F,TypeIDF1[i],df2); AReport.Add('%20s %4.0f %10.3f %10.3f %10.3f %8.3f', [Labels[i+1], TypeIDF1[i], TypeISS[i], TypeIMS[i], F, FProbF]); end; AReport.Add('%20s %4.0f %10.3f %10.3f', ['Residual', df2, SSres, VarEst]); AReport.Add('%20s %4d %10.3f', ['Total', totalobs-1, SSt]); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); end; // clean up the heap TypeIIProb := nil; TypeIIF := nil; TypeIProb := nil; TypeIF := nil; TypeIIDF2 := nil; TypeIIDF1 := nil; TypeIDF2 := nil; TypeIDF1 := nil; TypeIIMS := nil; TypeIMS := nil; TypeIISS := nil; TypeISS := nil; end; procedure TGLMFrm.ModelIIAnalysis(AReport: TStrings); var block, i, j, NEntered, index, noblocks : integer; NLeft, NRight : integer; cellstring : string; labelstr : string; begin NEntered := 0; OldR2 := 0; // enter the dependent variables first if NContDep > 0 then begin for i := 0 to NContDep - 1 do begin ColSelected[i] := ContDepPos[i]; Labels[i] := GenLabels[i+1]; NEntered := NEntered + 1; end; end; if NReptDep > 0 then begin for i := 0 to NReptDep - 1 do begin ColSelected[NEntered+i] := ReptDepPos[i]; Labels[NEntered+i] := GenLabels[NEntered+i+1]; NEntered := NEntered + 1; end; end; if NCatDep > 0 then begin for i := 0 to NCatDep - 1 do begin for j := 0 to NFixVecDep[i]-1 do begin ColSelected[NEntered+j] := CatDepPos[j]; Labels[NEntered+j] := GenLabels[NEntered+j+1]; NEntered := NEntered + 1; end; end; end; // Enter the no. of dependent variables in the left list box of canonical NLeft := NEntered; // Enter independent variables as indicated in indorderbox then interactions // until the total model is analyzed. Then delete each term to get a // restricted model and compare to the full model. noblocks := IndOrderBox.Items.Count; SetLength(TypeISS,noblocks); SetLength(TypeIISS,noblocks); SetLength(TypeIMS,noblocks); SetLength(TypeIIMS,noblocks); SetLength(TypeIDF1,noblocks); SetLength(TypeIDF2,noblocks); SetLength(TypeIIDF1,noblocks); SetLength(TypeIIDF2,noblocks); SetLength(TypeIF,noblocks); SetLength(TypeIProb,noblocks); SetLength(TypeIIF,noblocks); SetLength(TypeIIProb,noblocks); for block := 0 to noblocks - 1 do begin // get index of the abbreviation of term to enter and find corresponding // vector(s) to place in the equation cellstring := IndOrderBox.Items.Strings[block]; // check for covariates first if NCovIndep > 0 then begin for i := 0 to NCovIndep-1 do begin if cellstring = CovariateCode.Items.Strings[i] then // matched! begin index := i; // index of covariate code ColSelected[NEntered] := CovIndepPos[index]; labelstr := format('%s',[CovariateCode.Items.Strings[index]]); Labels[NEntered] := labelstr; NEntered := NEntered + 1; break; end; end; end; // check for fixed effect variables next if NFixedIndep > 0 then begin for i := 0 to NFixedIndep-1 do begin if cellstring = FixedIndepCode.Items.Strings[i] then begin index := i; for j := 0 to NFixVecIndep[index]-1 do begin ColSelected[NEntered] := FixedIndepPos[index] + j; labelstr := format('%s_%d',[FixedIndepCode.Items.Strings[index],j+1]); Labels[NEntered] := labelstr; NEntered := NEntered + 1; end; break; end; end; end; // Check for random effects variables next if NRndIndep > 0 then begin for i := 0 to NRndIndep-1 do begin if cellstring = RndIndepCode.Items.Strings[i] then begin index := i; for j := 0 to NRndVecIndep[index]-1 do begin ColSelected[NEntered] := RndIndepPos[index] + j; labelstr := format('%s_%d',[RndIndepCode.Items.Strings[index],j+1]); Labels[NEntered] := labelstr; NEntered := NEntered + 1; end; end; break; end; end; // check for interactions next if NoInterDefs > 0 then begin for i := 0 to NoInterDefs-1 do begin if cellstring = InteractList.Items.Strings[i] then begin for j := 0 to NInteractVecs[i]-1 do begin ColSelected[NEntered] := InteractPos[i] + j; labelstr := format('%s%d_%d',['IA',i+1,j+1]); Labels[NEntered] := labelstr; NEntered := NEntered + 1; end; end; break; end; end; // check for interaction variables // check for repeated measures variables (person codes) if NReptDep > 0 then begin // look for 'IP' in cellstring labelstr := copy(cellstring,0,2); if labelstr = 'IP' then // person vectors were generated begin for i := 0 to NoCases - 2 do begin ColSelected[NEntered] := ReptIndepPos[i]; Labels[NEntered] := GenLabels[ReptIndepPos[i]]; NEntered := NEntered + 1; end; end; end; // Enter the independent variables in the right list of canonical. NRight := NEntered - NLeft; // call cancor routine for this block CanCor(NLeft, NRight, ColSelected, AReport); end; // next block TypeIIProb := nil; TypeIIF := nil; TypeIProb := nil; TypeIIDF2 := nil; TypeIIDF1 := nil; TypeIDF2 := nil; TypeIDF1 := nil; TypeIIMS := nil; TYPEIMS := nil; TypeIISS := nil; TypeISS := nil; end; procedure TGLMFrm.ModelIIIAnalysis(AReport: TStrings); var block, i, j, NEntered, index, noblocks: integer; cellstring : string; labelstr : string; effstr : string; R, SSx, sum, constant: double; df1, df2, F, FProbF, StdErrB: double; SSt, VarEst, SSres, StdErrEst, AdjR2 : double; dfbetween, dferrbetween, dfwithin, dferrwithin : double; ssbetween, sserrbetween, mserrbetween, sswithin, sserrwithin, mserrwithin : double; betweenblock : integer; totalss, totaldf : double; begin OldR2 := 0; ColSelected[0] := ReptDepPos[0]; Labels[0] := GenLabels[1]; // Complete an individual regression analysis for each between subjects var. // Enter each block containing between subjects variance including: // (1) covariates // (2) person vectors // (3) fixed or random factors // (4) the interactions among only fixed or random effects noblocks := IndOrderBox.Items.Count; SetLength(TypeISS,noblocks); // use for between subject effects SetLength(TypeIISS,noblocks);// use for within subject effects SetLength(TypeIMS,noblocks); SetLength(TypeIIMS,noblocks); SetLength(TypeIDF1,noblocks); SetLength(TypeIDF2,noblocks); SetLength(TypeIIDF1,noblocks); SetLength(TypeIIDF2,noblocks); SetLength(TypeIF,noblocks); SetLength(TypeIProb,noblocks); SetLength(TypeIIF,noblocks); SetLength(TypeIIProb,noblocks); for i := 0 to noblocks - 1 do begin TypeISS[i] := -1.0; // store indicator for block (-1 indicates no use) TypeIISS[i] := -1.0; end; for block := 0 to noblocks - 1 do begin ColSelected[0] := ReptDepPos[0]; Labels[0] := GenLabels[1]; NEntered := 1; cellstring := IndOrderBox.Items.Strings[block]; effstr := cellstring; j := Pos('IR',cellstring); if j <> 0 then continue; // check for repeated measures variables (person codes) if NReptDep > 0 then begin // look for 'IP' in cellstring labelstr := copy(cellstring,0,2); if labelstr = 'IP' then // person vectors were generated begin betweenblock := block; // save block no. of between subject vectors for i := 0 to NoCases - 2 do begin ColSelected[NEntered] := ReptIndepPos[i]; Labels[NEntered] := GenLabels[ReptIndepPos[i]]; NEntered := NEntered + 1; end; end; end; // check for fixed effect variables next if NFixedIndep > 0 then begin for i := 0 to NFixedIndep-1 do begin if cellstring = FixedIndepCode.Items.Strings[i] then begin index := i; for j := 0 to NFixVecIndep[index]-1 do begin ColSelected[NEntered] := FixedIndepPos[index] + j; labelstr := Format('%s_%d', [FixedIndepCode.Items[index], j+1]); Labels[NEntered] := labelstr; NEntered := NEntered + 1; end; break; end; end; end; // Check for random effects variables next if NRndIndep > 0 then begin for i := 0 to NRndIndep-1 do begin if cellstring = RndIndepCode.Items.Strings[i] then begin index := i; for j := 0 to NRndVecIndep[index]-1 do begin ColSelected[NEntered] := RndIndepPos[index] + j; labelstr := Format('%s_%d', [RndIndepCode.Items[index], j+1]); Labels[NEntered] := labelstr; NEntered := NEntered + 1; end; break; end; end; end; // check for interactions next if NoInterDefs > 0 then begin for i := 0 to NoInterDefs-1 do begin if cellstring = InteractList.Items.Strings[i] then begin // eliminate any interactions containing 'IR' j := Pos('IR',cellstring); if j <> 0 then continue; for j := 0 to NInteractVecs[i]-1 do begin ColSelected[NEntered] := InteractPos[i] + j; labelstr := Format('%s%d_%d', ['IA',i+1,j+1]); Labels[NEntered] := labelstr; NEntered := NEntered + 1; end; break; end; end; end; // check for interaction variables // check for covariates if NCovIndep > 0 then begin for i := 0 to NCovIndep-1 do begin if cellstring = CovariateCode.Items.Strings[i] then // matched! begin index := i; // index of covariate code ColSelected[NEntered] := CovIndepPos[index]; labelstr := Format('%s', [CovariateCode.Items[index]]); Labels[NEntered] := labelstr; NEntered := NEntered + 1; break; end; end; end; // do reg analysis and save sum of squares RegAnal(NEntered, AReport); R := sqrt(R2); df1 := Nentered - 1; // no. of independent variables TypeIDF1[block] := df1; df2 := totalobs - df1 - 1; // N - no. independent - 1 SSt := (totalobs-1) * Vars[0]; SSres := SSt * (1.0 - R2); VarEst := SSres / df2; if (VarEst > 0.0) then StdErrEst := sqrt(VarEst) else begin ErrorMsg('Error in computing variance estimate.'); StdErrEst := 0.0; end; if (R2 < 1.0) and (df2 > 0.0) then F := (R2 / df1) / ((1.0-R2)/ df2) else F := 0.0; FProbF := probf(F,df1,df2); AdjR2 := 1.0 - (1.0 - R2) * (totalobs - 1) / df2; AReport.Add(' R R2 F Prob. > F DF1 DF2 '); AReport.Add('-------- ---------- ---------- ---------- ----- -----'); AReport.Add('%8.3f %10.3f %10.3f %10.3f %5.0f %5.0f', [R, R2, F, FProbF, df1, df2]); AReport.Add('Adjusted R Squared: %10.3f', [AdjR2]); AReport.Add(''); AReport.Add('Std. Error of Estimate: %10.3f', [StdErrEst]); AReport.Add(''); AReport.Add('Variable Beta B Std.Error t Prob. > t '); AReport.Add('---------- ---------- ---------- ---------- ---------- ----------'); df1 := 1.0; sum := 0.0; for i := 0 to Nentered - 2 do begin SSx := (totalobs-1) * Vars[i+1]; sum := sum + B[i] * means[i+1]; if invmatrix[i,i] > 1.0e-15 then begin StdErrB := VarEst / (SSx * (1.0 / invmatrix[i,i])); StdErrB := sqrt(StdErrB); if StdErrB > 0.0 then F := B[i] / StdErrB else F := 0.0; FProbF := probf(F*F,df1,df2); end else begin StdErrB := 0.0; F := 0.0; FProbF := 0.0; end; cellstring := Format('%10s', [Labels[i+1]]); AReport.Add('%10s %10.3f %10.3f %10.3f %10.3f %10.3f', [cellstring, Beta[i] ,B[i], StdErrB, F, FProbF]); end; constant := means[0] - sum; AReport.Add('Constant: %10.3f', [constant]); TypeISS[block] := R2 * SST; AReport.Add('BETWEEN SUBJECT EFFECT:'); AReport.Add('SS for %-10s: %10.3f',[effstr,TypeISS[block]]); AReport.Add('SS TOTAL: %10.3f',[SST]); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); end; // Summarize between subject effects totalss := 0.0; totaldf := 0.0; for i := 0 to noblocks - 1 do begin if TypeISS[i] < 0.0 then continue; if betweenblock = i then begin ssbetween := TypeISS[i]; dfbetween := TypeIDF1[i]; end else begin totalss := totalss + TypeISS[i]; totaldf := totaldf + TypeIDF1[i]; end; end; sserrbetween := ssbetween - totalss; dferrbetween := dfbetween - totaldf; mserrbetween := sserrbetween / dferrbetween; AReport.Add('SUMMARY OF BETWEEN SUBJECT EFFECTS'); AReport.Add('SOURCE DF SS MS F Prob > F'); AReport.Add('-------------------- ---- ---------- ---------- ---------- --------'); AReport.Add('%-20s %4.0f %10.3f', ['Between Subjects', dfbetween, ssbetween]); for i := 0 to noblocks - 1 do begin if TypeISS[i] < 0.0 then continue; if betweenblock = i then continue; // already done above TypeIMS[i] := TypeISS[i] / TypeIDF1[i]; TypeIF[i] := TypeIMS[i] / mserrbetween; TypeIDF2[i] := dferrbetween; TypeIProb[i] := probf(TypeIF[i],TypeIDF1[i],TypeIDF2[i]); AReport.Add('%20s %4.0f %10.3f %10.3f %10.3f %10.3f', [IndOrderBox.Items[i], TypeIDF1[i], TypeISS[i], TypeIMS[i], TypeIF[i], TypeIProb[i]] ); end; AReport.Add('%20s %4.0f %10.3f %10.3f', ['Error Between', dferrbetween, sserrbetween, mserrbetween]); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); // Now, get within subject effects sswithin := SST - SSbetween; dfwithin := totalobs - dfbetween - 1; for block := 0 to noblocks - 1 do begin ColSelected[0] := ReptDepPos[0]; Labels[0] := GenLabels[1]; NEntered := 1; cellstring := IndOrderBox.Items.Strings[block]; effstr := cellstring; j := Pos('IR',cellstring); if j = 0 then continue; // only select those for rep. treatments or interactions // check for treatments if NReptDep > 0 then begin // look for 'IR' in cellstring labelstr := copy(cellstring,0,2); if labelstr = 'IR' then // repeated treatment vectors were generated begin for i := 0 to NReptDep - 2 do begin ColSelected[NEntered] := ReptTrtPos[i]; Labels[NEntered] := GenLabels[ReptTrtPos[i]]; NEntered := NEntered + 1; end; end; end; // check for interactions next if NoInterDefs > 0 then begin for i := 0 to NoInterDefs-1 do begin if cellstring = InteractList.Items.Strings[i] then begin for j := 0 to NInteractVecs[i]-1 do begin ColSelected[NEntered] := InteractPos[i] + j; labelstr := format('%s%d_%d',['IA',i+1,j+1]); Labels[NEntered] := labelstr; NEntered := NEntered + 1; end; break; end; end; end; // check for interaction variables // do reg analysis and save sum of squares if NEntered < 2 then continue; RegAnal(NEntered, AReport); R := sqrt(R2); df1 := Nentered - 1; // no. of independent variables TypeIIDF1[block] := df1; df2 := totalobs - df1 - 1; // N - no. independent - 1 SSt := (totalobs-1) * Vars[0]; SSres := SSt * (1.0 - R2); VarEst := SSres / df2; if (VarEst > 0.0) then StdErrEst := sqrt(VarEst) else begin MessageDlg('Error in computing variance estimate.', mtError,[mbOK], 0); StdErrEst := 0.0; end; if (R2 < 1.0) and (df2 > 0.0) then F := (R2 / df1) / ((1.0-R2)/ df2) else F := 0.0; FProbF := probf(F,df1,df2); AdjR2 := 1.0 - (1.0 - R2) * (totalobs - 1) / df2; AReport.Add(' R R2 F Prob. > F DF1 DF2 '); AReport.Add('-------- ---------- ---------- ---------- ----- -----'); AReport.Add('%8.3f %10.3f %10.3f %10.3f %5.0f %5.0f', [R, R2, F, FProbF, df1, df2]); AReport.Add(''); AReport.Add('Adjusted R Squared: %10.3f', [AdjR2]); AReport.Add('Std. Error of Estimate: %10.3f', [StdErrEst]); AReport.Add(''); AReport.Add('Variable Beta B Std.Error t Prob. > t '); AReport.Add('---------- ---------- ---------- ---------- ---------- ----------'); df1 := 1.0; sum := 0.0; for i := 0 to Nentered - 2 do begin SSx := (totalobs-1) * Vars[i+1]; sum := sum + B[i] * means[i+1]; if invmatrix[i,i] > 1.0e-15 then begin StdErrB := VarEst / (SSx * (1.0 / invmatrix[i,i])); StdErrB := sqrt(StdErrB); if StdErrB > 0.0 then F := B[i] / StdErrB else F := 0.0; FProbF := probf(F*F,df1,df2); end else begin StdErrB := 0.0; F := 0.0; FProbF := 0.0; end; cellstring := Format('%10s', [Labels[i+1]]); AReport.Add('%10s %10.3f %10.3f %10.3f %10.3f %10.3f', [cellstring, Beta[i] ,B[i], StdErrB, F, FProbF]); end; constant := means[0] - sum; AReport.Add('Constant: %10.3f', [constant]); TypeIISS[block] := R2 * SST; AReport.Add('BETWEEN SUBJECT EFFECT:'); AReport.Add('SS for %-10s: %10.3f',[effstr, TypeIISS[block]]); AReport.Add('SS TOTAL: %10.3f',[SST]); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); end; totalss := 0.0; totaldf := 0.0; for i := 0 to noblocks - 1 do // add sums of squares for within effects begin if TypeIISS[i] < 0.0 then continue; totalss := totalss + TypeIISS[i]; totaldf := totaldf + TypeIIDF1[i]; end; sserrwithin := sswithin - totalss; dferrwithin := dfwithin - totaldf; mserrwithin := sserrwithin / dferrwithin; AReport.Add(' SUMMARY OF WITHIN SUBJECT EFFECTS'); AReport.Add('SOURCE DF SS MS F Prob > F'); AReport.Add('-------------------- ---- ---------- ---------- ---------- --------'); AReport.Add('%-20s %4.0f %10.3f', ['Within Subjects', dfwithin, sswithin]); for i := 0 to noblocks - 1 do begin if TypeIISS[i] < 0.0 then continue; TypeIIMS[i] := TypeIISS[i] / TypeIIDF1[i]; TypeIIF[i] := TypeIIMS[i] / mserrwithin; TypeIIDF2[i] := dferrwithin; TypeIIProb[i] := probf(TypeIIF[i],TypeIIDF1[i],TypeIIDF2[i]); AReport.Add('%20s %4.0f %10.3f %10.3f %10.3f %10.3f', [IndOrderBox.Items.Strings[i],TypeIIDF1[i],TypeIISS[i],TypeIIMS[i],TypeIIF[i],TypeIIProb[i]] ); end; AReport.Add('%20s %4.0f %10.3f %10.3f', ['Error Within', dferrwithin, sserrwithin, mserrwithin]); AReport.Add('%20s %4d %10.3f', ['TOTAL', totalobs-1, SST]); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); // clean up the heap TypeIIProb := nil; TypeIIF := nil; TypeIProb := nil; TypeIF := nil; TypeIIDF2 := nil; TypeIIDF1 := nil; TypeIDF2 := nil; TypeIDF1 := nil; TypeIIMS := nil; TypeIMS := nil; TypeIISS := nil; TypeISS := nil; end; function TGLMFrm.CntIntActVecs(linestr: string): integer; var i, j, listcnt, varcount : integer; cellstring : string; asterisk : string; blank : string; abbrevList : array[1..5] of string; vectcnt : array[1..5] of integer; newline : string; begin asterisk := '*'; blank := ' '; listcnt := 0; cellstring := ''; newline := ''; for i := 1 to 5 do vectcnt[i] := 0; // first, delete imbedded blanks that were there for readability for i := 1 to length(linestr) do begin if linestr[i] <> blank then newline := newline + linestr[i]; end; // Now, strip out substrings to each asterisk or end of string while length(newline) > 0 do begin i := pos(asterisk,newline); if i > 0 then // an asterisk found begin cellstring := copy(newline,0,i-1); // get abbreviation delete(newline,1,i); // delete abbreviation and asterisk listcnt := listcnt + 1; AbbrevList[listcnt] := cellstring; end else begin // must be last abbreviation cellstring := newline; listcnt := listcnt + 1; AbbrevList[listcnt] := cellstring; newline := ''; end; end; // now get the associated number of columns for each abbreviation in the list for i := 1 to listcnt do begin cellstring := AbbrevList[i]; // check for covariates if NCovIndep > 0 then begin for j := 0 to NCovIndep - 1 do begin if cellstring = CovariateCode.Items.Strings[j] then vectcnt[i] := 1; end; end; // check for fixed effect vectors if NFixedIndep > 0 then begin for j := 0 to NFixedIndep - 1 do begin if cellstring = FixedIndepCode.Items.Strings[j] then vectcnt[i] := NFixVecIndep[j]; end; end; // check for random effect vectors if NRndIndep > 0 then begin for j := 0 to NRndIndep - 1 do begin if cellstring = RndIndepCode.Items.Strings[j] then vectcnt[i] := NRndVecIndep[j]; end; end; // check for repeated measures effect vectors if NReptDep > 0 then begin if cellstring = RepTrtCode.Items.Strings[0] then vectcnt[i] := NReptDep - 1; end; end; // next i in listcnt // get total interaction vector count varcount := 1; for i := 1 to listcnt do varcount := varcount * vectcnt[i]; Result := varcount; end; procedure TGLMFrm.GenInterVecs(linestr: string); var i, j, k, l, m, n, col, listcnt, pos1, pos2, pos3, pos4, pos5: integer; cellstring : string; asterisk : string; blank : string; abbrevList : array[1..5] of string; vectcnt : array[1..5] of integer; fromcol : array[1..5] of integer; newline : string; begin asterisk := '*'; blank := ' '; listcnt := 0; cellstring := ''; newline := ''; // first, delete imbedded blanks that were there for readability for i := 1 to length(linestr) do begin if linestr[i] <> blank then newline := newline + linestr[i]; end; // Now, strip out substrings to each asterisk or end of string while length(newline) > 0 do begin i := pos(asterisk,newline); if i > 0 then // an asterisk found begin cellstring := copy(newline,0,i-1); // get abbreviation delete(newline,1,i); // delete abbreviation and asterisk listcnt := listcnt + 1; AbbrevList[listcnt] := cellstring; end else begin // must be last abbreviation cellstring := newline; listcnt := listcnt + 1; AbbrevList[listcnt] := cellstring; newline := ''; end; end; // now generate the associated number of columns for each abbreviation in the list for i := 1 to listcnt do begin cellstring := AbbrevList[i]; // check for covariates if NCovIndep > 0 then begin for j := 0 to NCovIndep - 1 do begin if cellstring = CovariateCode.Items.Strings[j] then begin vectcnt[i] := 1; fromcol[i] := CovIndepPos[j]; break; end; end; end; // check for fixed effect vectors if NFixedIndep > 0 then begin for j := 0 to NFixedIndep - 1 do begin if cellstring = FixedIndepCode.Items.Strings[j] then begin vectcnt[i] := NFixVecIndep[j]; fromcol[i] := FixedIndepPos[j]; break; end; end; end; // check for random effect vectors if NRndIndep > 0 then begin for j := 0 to NRndIndep - 1 do begin if cellstring = RndIndepCode.Items.Strings[j] then begin vectcnt[i] := NRndVecIndep[j]; fromcol[i] := RndIndepPos[j]; break; end; end; end; // check for repeated measures if NReptDep > 0 then begin if cellstring = RepTrtCode.Items.Strings[0] then begin vectcnt[i] := NReptDep - 1; fromcol[i] := ReptTrtPos[0]; end; end; end; // next i in listcnt // now generate the product vectors for 2-way interactions col := gencount; for i := 1 to vectcnt[1] do begin pos1 := fromcol[1] + i - 1; for j := 1 to vectcnt[2] do begin pos2 := fromcol[2] + j - 1; for m := 0 to totalobs - 1 do datagrid[m,col] := datagrid[m,pos1] * datagrid[m,pos2]; cellstring := format('%s_%d*%s_%d',[AbbrevList[1],i,AbbrevList[2],j]); GenLabels[col] := cellstring; col := col + 1; end; end; if listcnt = 3 then // Do 3-way interactions begin col := gencount; for i := 1 to vectcnt[1] do begin pos1 := fromcol[1] + i - 1; for j := 1 to vectcnt[2] do begin pos2 := fromcol[2] + j - 1; for k := 1 to vectcnt[3] do begin pos3 := fromcol[3] + k - 1; for m := 0 to totalobs - 1 do datagrid[m,col] := datagrid[m,pos1] * datagrid[m,pos2] * datagrid[m,pos3]; cellstring := format('%s*%s*%s',[GenLabels[pos1],GenLabels[pos2],GenLabels[pos3]]); GenLabels[col] := cellstring; col := col + 1; end; // next k end; // next j end; // next i end; // if listcnt = 3 if listcnt = 4 then // Do 4-way interactions begin col := gencount; for i := 1 to vectcnt[1] do begin pos1 := fromcol[1] + i - 1; for j := 1 to vectcnt[2] do begin pos2 := fromcol[2] + j - 1; for k := 1 to vectcnt[3] do begin pos3 := fromcol[3] + k - 1; for l := 1 to vectcnt[4] do begin pos4 := fromcol[4] + l - 1; for m := 0 to totalobs - 1 do datagrid[m,col] := datagrid[m,pos1] * datagrid[m,pos2] * datagrid[m,pos3] * datagrid[m,pos4]; cellstring := format('%s*%s*%s*%s',[GenLabels[pos1], GenLabels[pos2],GenLabels[pos3],GenLabels[pos4]]); GenLabels[col] := cellstring; col := col + 1; end; // next l end; // next k end; // next j end; // next i end; // if listcnt = 3 if listcnt = 5 then // Do 5-way interactions begin col := gencount; for i := 1 to vectcnt[1] do begin pos1 := fromcol[1] + i - 1; for j := 1 to vectcnt[2] do begin pos2 := fromcol[2] + j - 1; for k := 1 to vectcnt[3] do begin pos3 := fromcol[3] + k - 1; for l := 1 to vectcnt[4] do begin pos4 := fromcol[4] + l - 1; for n := 1 to vectcnt[5] do begin pos5 := fromcol[5] + n - 1; for m := 0 to totalobs - 1 do datagrid[m,col] := datagrid[m,pos1] * datagrid[m,pos2] * datagrid[m,pos3] * datagrid[m,pos4] * datagrid[m,pos5]; cellstring := Format('%s*%s*%s*%s*%s',[GenLabels[pos1], GenLabels[pos2],GenLabels[pos3],GenLabels[pos4], GenLabels[pos5]]); GenLabels[col] := cellstring; col := col + 1; end; // next n end; // next l end; // next k end; // next j end; // next i end; // if listcnt = 3 end; procedure TGLMFrm.CanCor(NLeft: integer; NRight: integer; GridPlace: IntDyneVec; AReport: TStrings); var i, j, k, count, a_size, b_size, no_factors, IER: integer; s, m, n, df1, df2, q, w, pcnt_extracted, trace : double; minroot, critical_prob, Lambda, Pillia : double; chisqr, HLTrace, chiprob, ftestprob, Roys, f, Hroot : double; raa, rbb, rab, rba, bigmat, first_prod, second_prod : DblDyneMat; char_equation, raainv, rbbinv, eigenvectors, norm_a, norm_b : DblDyneMat; raw_a, raw_b, a_cors, b_cors, eigentrans, theta, tempmat : DblDyneMat; mean, variance, stddev, roots, root_chi, chi_prob, pv_a, pv_b : DblDyneVec; rd_a, rd_b, pcnt_trace : DblDyneVec; root_df : IntDyneVec; a_vars, b_vars : StrDyneVec; selected : IntDyneVec; RowLabels, ColLabels : StrDyneVec; CanLabels : StrDyneVec; title : string; errorcode : boolean = false; begin count := 0; k := 0; no_factors := 0; pcnt_extracted := 0.0; trace := 0.0; minroot := 0.0; critical_prob := 0.0; Pillia := 0.0; chisqr := 0.0; HLTrace := 0.0; chiprob := 0.0; // Get size of the Left and Right matrices (predictors and dependents) a_size := NLeft; b_size:= NRight; novars:= a_size + b_size; // allocate memory for matrices and vectors SetLength(raa,NLeft+1,NLeft+1); SetLength(rbb,NRight+1,NRight+1); SetLength(rab,NLeft+1,NRight+1); SetLength(rba,NRight+1,NLeft+1); SetLength(bigmat,novars+1,novars+1); SetLength(first_prod,novars+1,novars+1); SetLength(second_prod,novars+1,novars+1); SetLength(char_equation,novars+1,novars+1); SetLength(raainv,NLeft,NLeft); SetLength(rbbinv,NRight,NRight); SetLength(eigenvectors,novars,novars); SetLength(norm_a,novars,novars); SetLength(norm_b,novars,novars); SetLength(raw_a,novars,novars); SetLength(raw_b,novars,novars); SetLength(a_cors,NLeft+1,NLeft+1); SetLength(b_cors,NRight+1,NRight+1); SetLength(eigentrans,novars,novars); SetLength(theta,novars,novars); SetLength(tempmat,novars,novars); SetLength(mean,novars); SetLength(variance,novars); SetLength(stddev,novars); SetLength(roots,novars); SetLength(root_chi,novars); SetLength(chi_prob,novars); SetLength(pv_a,novars); SetLength(pv_b,novars); SetLength(rd_a,novars); SetLength(rd_b,novars); SetLength(pcnt_trace,novars); SetLength(root_df,novars); SetLength(a_vars,NLeft); SetLength(b_vars,NRight); SetLength(CanLabels,novars); SetLength(RowLabels,novars); SetLength(ColLabels,novars); SetLength(selected,novars); //------------ WORK STARTS HERE! ------------------------------------- // Build labels for canonical functions 1 to novars if b_size < a_size then for i := 0 to b_size-1 do CanLabels[i] := 'CanVar' + IntToStr(i+1) else for i := 0 to a_size-1 do CanLabels[i] := 'CanVar' + IntToStr(i+1); for i := 0 to a_size - 1 do // identify left variables begin a_vars[i] := Labels[i]; selected[i] := GridPlace[i]; end; for i := 0 to b_size - 1 do // identify right variables begin b_vars[i] := Labels[NLeft+i]; selected[NLeft+i] := GridPlace[NLeft+i]; end; AReport.Add('CANONICAL CORRELATION ANALYSIS'); AReport.Add(''); count := NoCases; // Get means, standard deviations, etc. for total matrix IER := DynCorrelations(novars,selected,datagrid,bigmat,mean,variance,stddev,totalobs,3); if (IER = 1) then begin ErrorMsg('Zero variance found for a variable-terminating'); exit; end; //partition matrix into quadrants for i := 0 to a_size - 1 do for j := 0 to a_size - 1 do raa[i,j]:= bigmat[i,j]; for i := a_size to novars - 1 do for j := a_size to novars - 1 do rbb[i-a_size,j-a_size] := bigmat[i,j]; for i := 0 to a_size - 1 do for j := a_size to novars - 1 do rab[i,j-a_size] := bigmat[i,j]; for i := a_size to novars - 1 do for j := 0 to a_size - 1 do rba[i-a_size,j] := bigmat[i,j]; if CorsChk.Checked then begin title := 'Left Correlation Matrix'; MatPrint(raa, NLeft, NLeft, title, a_vars, a_vars, totalobs, AReport); title := 'Right Correlation Matrix'; MatPrint(rbb, NRight, NRight, title, b_vars, b_vars, totalobs, AReport); title := 'Left-Right Correlation Matrix'; MatPrint(rab, NLeft, NRight, title, a_vars, b_vars, totalobs, AReport); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); end; // get inverses of left and right hand matrices raa and rbb for i := 0 to a_size-1 do for j := 0 to a_size-1 do tempmat[i,j] := raa[i,j]; SVDInverse(tempmat,a_size); for i := 0 to a_size-1 do for j := 0 to a_size-1 do raainv[i,j] := tempmat[i,j]; if CorsChk.Checked then begin title := 'Inverse of Left Matrix'; MatPrint(raainv, a_size, a_size, title, a_vars, a_vars, totalobs, AReport); end; for i := 0 to b_size-1 do for j := 0 to b_size-1 do tempmat[i,j] := rbb[i,j]; // inverse uses 1 offset SVDInverse(tempmat,b_size); for i := 0 to b_size-1 do // reset to 0 offset for j := 0 to b_size - 1 do rbbinv[i,j] := tempmat[i,j]; if CorsChk.Checked then begin title := 'Inverse of Right Matrix'; MatPrint(rbbinv, b_size, b_size, title, b_vars, b_vars, totalobs, AReport); end; // get products of raainv x rab and the rbbinv x rba matrix for i := 0 to b_size-1 do for j := 0 to a_size-1 do first_prod[i,j] := 0.0; MatAxB(first_prod,rbbinv,rba,b_size,b_size,b_size,a_size,errorcode); for i := 0 to a_size-1 do for j := 0 to b_size-1 do second_prod[i,j] := 0.0; MatAxB(second_prod,raainv,rab,a_size,a_size,a_size,b_size,errorcode); title := 'Right Inverse x Right-Left Matrix'; MatPrint(first_prod, b_size, a_size, title, b_vars, a_vars, totalobs, AReport); title := 'Left Inverse x Left-Right Matrix'; MatPrint(second_prod, a_size, b_size, title, a_vars, b_vars, totalobs, AReport); //get characteristic equations matrix (product of last two product matrices //The product should yeild rows and cols representing the smaller of the two sets for i := 0 to b_size-1 do for j := 0 to b_size - 1 do char_equation[i,j] := 0.0; MatAxB(char_equation,first_prod,second_prod,b_size,a_size,a_size,b_size,errorcode); title := 'Canonical Function'; MatPrint(char_equation, b_size, b_size, title, CanLabels, CanLabels, totalobs, AReport); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); // now get roots and vectors of the characteristic equation using // NonSymRoots routine minroot := 0.0; for i := 0 to b_size - 1 do begin roots[i] := 0.0; pcnt_trace[i] := 0.0; for j := 0 to b_size - 1 do eigenvectors[i,j] := 0.0; end; trace := 0.0; no_factors := b_size; Dynnonsymroots(char_equation, b_size, no_factors, minroot, eigenvectors, roots, pcnt_trace, trace, pcnt_extracted); AReport.Add('Trace of the matrix: %10.4f', [trace]); AReport.Add('Percent of trace extracted: %10.4f', [pcnt_extracted]); // Normalize smaller set weights and coumpute larger set weights for i := 0 to b_size - 1 do // transpose eigenvectors for j := 0 to b_size - 1 do eigentrans[j,i] := eigenvectors[i,j]; for i := 0 to b_size - 1 do for j := 0 to b_size-1 do tempmat[i,j] := 0.0; MatAxB(tempmat,eigentrans,rbb,b_size,b_size,b_size,b_size,errorcode); for i := 0 to b_size-1 do for j := 0 to b_size-1 do theta[i,j] := 0.0; MatAxB(theta,tempmat,eigenvectors,b_size,b_size,b_size,b_size,errorcode); for j := 0 to b_size - 1 do begin q := 1.0 / sqrt(theta[j,j]); for i := 0 to b_size - 1 do begin norm_b[i,j] := eigenvectors[i,j] * q; raw_b[i,j] := norm_b[i,j] / stddev[a_size+i]; end; end; for i := 0 to a_size - 1 do for j := 0 to b_size - 1 do norm_a[i,j] := 0.0; MatAxB(norm_a,second_prod,norm_b,a_size,b_size,b_size,b_size,errorcode); for j := 0 to b_size-1 do begin for i := 0 to a_size-1 do begin norm_a[i,j] := norm_a[i,j] * (1.0 / sqrt(roots[j])); raw_a[i,j] := norm_a[i,j] / stddev[i]; end; end; // Compute the correlations between variables and canonical variables for i := 0 to a_size-1 do for j := 0 to b_size-1 do a_cors[i,j] := 0.0; MatAxB(a_cors,raa,norm_a,a_size,a_size,a_size,b_size,errorcode); for j := 0 to b_size-1 do begin q := 0.0; for i := 0 to a_size-1 do q := q + norm_a[i,j] * a_cors[i,j]; q := 1.0 / sqrt(q); for i := 0 to a_size-1 do a_cors[i,j] := a_cors[i,j] * q; end; for i := 0 to b_size-1 do for j := 0 to b_size-1 do b_cors[i,j] := 0.0; MatAxB(b_cors,rbb,norm_b,b_size,b_size,b_size,b_size,errorcode); for j := 0 to b_size-1 do begin q := 0.0; for i := 0 to b_size-1 do q := q + norm_b[i,j] * b_cors[i,j]; q := 1.0 / sqrt(q); for i := 0 to b_size-1 do b_cors[i,j] := b_cors[i,j] * q; end; // Compute the Proportions of Variance (PVs) and Redundancy Coefficients for j := 0 to b_size-1 do begin pv_a[j] := 0.0; for i := 0 to a_size-1 do pv_a[j] := pv_a[j] + (a_cors[i,j] * a_cors[i,j]); pv_a[j] := pv_a[j] / a_size; rd_a[j] := pv_a[j] * roots[j]; end; for j := 0 to b_size-1 do begin pv_b[j] := 0.0; for i := 0 to b_size-1 do pv_b[j] := pv_b[j] + (b_cors[i,j] * b_cors[i,j]); pv_b[j] := pv_b[j] / b_size; rd_b[j] := pv_b[j] * roots[j]; end; // Compute tests of the roots q := a_size + b_size + 1; q := -(count - 1.0 - (q / 2.0)); k := 0; for i := 0 to b_size-1 do begin w := 1.0; for j := i to b_size-1 do w := w * (1.0 - roots[j]); root_chi[i] := q * ln(w); root_df[i] := (a_size - i) * (b_size - i); chi_prob[i] := 1.0 - chisquaredprob(root_chi[i],root_df[i]); if (chi_prob[i] < critical_prob) then k := k + 1; end; Roys := roots[1] / (1.0 - roots[1]); Lambda := 1.0; for i := 0 to b_size-1 do begin Hroot := roots[i] / (1.0 - roots[i]); Lambda := Lambda * (1.0 / (1.0 + Hroot)); Pillia := Pillia + (Hroot / (1.0 + Hroot)); HLTrace := HLTrace + Hroot; end; // Print remaining results AReport.Add(''); AReport.Add(''); AReport.Add(' Canonical R Root % Trace Chi-Sqr D.F. Prob.'); for i := 0 to b_size-1 do AReport.Add('%2d %10.6f %8.3f %7.3f %8.3f %2d %8.3f', [i+1, sqrt(roots[i]), roots[i], pcnt_trace[i], root_chi[i], root_df[i], chi_prob[i]]); chisqr := -ln(Lambda) * (count - 1.0 - 0.5 * (a_size + b_size - 1.0)); chiprob := 1.0 - chisquaredprob(chisqr,a_size * b_size); AReport.Add(''); AReport.Add('Overall Tests of Significance:'); AReport.Add(' Statistic Approx. Stat. Value D.F. Prob.>Value'); AReport.Add('Wilk''s Lambda Chi-Squared %10.4f %3d %6.4f', [chisqr,a_size * b_size,chiprob]); s := b_size; m := 0.5 * (a_size - b_size - 1); n := 0.5 * (count - b_size - a_size - 2); f := (HLTrace * 2.0 * (s * n + 1)) / (s * s * (2.0 * m + s + 1.0)); df1 := s * (2.0 * m + s + 1.0); df2 := 2.0 * ( s * n + 1.0); ftestprob := probf(f,df1,df2); AReport.Add('Hotelling-Lawley Trace F-Test %10.4f %2.0f %2.0f %6.4f', [f, df1, df2, ftestprob]); df2 := s * (2.0 * n + s + 1.0); f := (Pillia / (s - Pillia)) * ( (2.0 * n + s +1.0) / (2.0 * m + s + 1.0) ); ftestprob := probf(f,df1,df2); AReport.Add('Pillai Trace F-Test %10.4f %2.0f %2.0f %6.4f', [f, df1, df2, ftestprob]); Roys := Roys * (count - 1 - a_size + b_size)/ a_size ; df1 := a_size; df2 := count - 1 - a_size + b_size; ftestprob := probf(Roys,df1,df2); AReport.Add('Roys Largest Root F-Test %10.4f %2.0f %2.0f %6.4f', [Roys, df1, df2, ftestprob]); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); if CorsChk.Checked then begin title := 'Eigenvectors'; MatPrint(eigenvectors, b_size, b_size, title, CanLabels, CanLabels, totalobs, AReport); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); end; title := 'Standardized Right Side Weights'; MatPrint(norm_a, a_size, b_size, title, RowLabels, CanLabels, totalobs, AReport); title := 'Standardized Left Side Weights'; MatPrint(norm_b, b_size, b_size, title, ColLabels, CanLabels, totalobs, AReport); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); title := 'Raw Right Side Weights'; MatPrint(raw_a, a_size, b_size, title, RowLabels, CanLabels, totalobs, AReport); title := 'Raw Left Side Weights'; MatPrint(raw_b, b_size, b_size, title, ColLabels, CanLabels, totalobs, AReport); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); title := 'Right Side Correlations with Function'; MatPrint(a_cors, a_size, b_size, title, RowLabels, CanLabels, totalobs, AReport); title := 'Left Side Correlations with Function'; MatPrint(b_cors, b_size, b_size, title, ColLabels, CanLabels, totalobs, AReport); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); if CorsChk.Checked then begin AReport.Add('Redundancy Analysis for Right Side Variables'); AReport.Add(''); AReport.Add(' Variance Prop. Redundancy'); for i := 0 to b_size-1 do AReport.Add('%10d %10.5f %10.5f', [i, pv_a[i], rd_a[i]]); AReport.Add(''); AReport.Add('Redundancy Analysis for Left Side Variables'); AReport.Add(' Variance Prop. Redundancy'); for i := 0 to b_size-1 do AReport.Add('%10d %10.5f %10.5f', [i, pv_b[i], rd_b[i]]); AReport.Add(''); AReport.Add(DIVIDER); AReport.Add(''); end; //------------- Now, clean up memory mess ---------------------------- selected := nil; ColLabels := nil; RowLabels := nil; CanLabels := nil; b_vars := nil; a_vars := nil; root_df := nil; pcnt_trace := nil; rd_b := nil; rd_a := nil; pv_b := nil; pv_a := nil; chi_prob := nil; root_chi := nil; roots := nil; stddev := nil; variance := nil; mean := nil; tempmat := nil; theta := nil; eigentrans := nil; b_cors := nil; a_cors := nil; raw_b := nil; raw_a := nil; norm_b := nil; norm_a := nil; eigenvectors := nil; rbbinv := nil; raainv := nil; char_equation := nil; second_prod := nil; first_prod := nil; bigmat := nil; rba := nil; rab := nil; rbb := nil; raa := nil; end; procedure TGLMFrm.UpdateBtnStates; begin ContDepInBtn.Enabled := VarList.ItemIndex > -1; ContDepOutBtn.Enabled := DepContList.ItemIndex > -1; CatDepInBtn.Enabled := VarList.ItemIndex > -1; CatDepOutBtn.Enabled := DepCatList.ItemIndex > -1; ReptDepInBtn.Enabled := AnySelected(VarList); ReptDepOutBtn.Enabled := RepeatList.ItemIndex > -1; FixedIndepInBtn.Enabled := AnySelected(VarList); FixedIndepOutBtn.Enabled := FixedList.ItemIndex > -1; RndIndepInBtn.Enabled := VarList.ItemIndex > -1; RndIndepOutBtn.Enabled := RandomList.ItemIndex > -1; CovInBtn.Enabled := VarList.ItemIndex > -1; CovOutBtn.Enabled := CovariateList.ItemIndex > -1; end; initialization {$I glmunit.lrs} end.