'Do Median Polishing 'make a list of fields that will be included theTable = av.GetActiveDoc theVtab = theTable.GetVtab aFieldlist = List.Make for each f in theVtab.GetFields 'only look for the numeric, visible fields if ( f.IsVisible ) then aFieldList = aFieldList.Add(f.GetAlias) end end 'get the variable to use as the rows TheRowName = MsgBox.ListAsString(aFieldList, "Choose the field to use as rows","MP Rows") if (TheRowName <> nil) then TheRow = theVtab.FindField(TheRowName) end 'get the variable to use as the columns TheColName = MsgBox.ListAsString(aFieldList, "Choose the field to use as columns","MP Columns") if (TheColName <> nil) then TheCol = theVtab.FindField(TheColName) end 'get the variable to use as the data TheDataName = MsgBox.ListAsString(aFieldList, "Choose the field to use as data","MP Data") if (TheDataName <> nil) then TheData = theVtab.FindField(TheDataName) end 'determine the number of rows (nr) and columns (nc) oldRowVal = 0 nr = 0 rowList = List.Make oldColVal = 0 colList = List.Make nc = 0 n = theVtab.GetNumRecords for each rec in theVtab if (theVtab.ReturnValue(theData,rec).IsNull) then continue else newRowVal = theVtab.ReturnValue(theRow,rec) newColVal = theVtab.ReturnValue(theCol,rec) if (rowList.FindByValue(newRowVal) = -1) then nr = nr + 1 oldRowVal = newRowVal rowList.Add(newRowVal) end if (colList.FindByValue(newColVal) = -1) then nc = nc + 1 oldColVal = newColVal colList.Add(newColVal) end end end 'Make the Vtab editable if (theVtab.IsEditable = False) then theVtab.StartEditingWithRecovery end 'make new fields for RowEffects, ColEffects, 'AllEffect, and resid if they do not exist, or get them 'from the Vtab if they do if(theVtab.FindField("RowEffects") = nil) then re = Field.Make("RowEffects",#FIELD_FLOAT,12,4) ce = Field.Make("ColEffects",#FIELD_FLOAT,12,4) all = Field.Make("AllEffect",#FIELD_FLOAT,12,4) resid = Field.Make("residuals",#FIELD_FLOAT,12,4) theVtab.AddFields({re,ce,all,resid}) else re = theVtab.FindField("RowEffects") ce = theVtab.FindField("ColEffects") all = theVtab.FindField("AllEffect") resid = theVtab.FindField("residuals") end 'Initialize the row effects(re), col effects(ce), all effect(all) '& Istep to 0, and the residuals(resid) to the data for each rec in theVtab if((rowList.FindByValue(theVtab.ReturnValue(theRow,rec))> -1)and (colList.FindByValue(theVtab.ReturnValue(theCol,rec))> -1)) then theVtab.SetValueNumber(re,rec,0) theVtab.SetValueNumber(ce,rec,0) theVtab.SetValueNumber(all,rec,0) else continue end rvalue=theVtab.ReturnValue(theData,rec) if(rvalue.IsNull = False) then theVtab.SetValueNumber(resid,rec,rvalue) else continue end end Istep = 0 non0 = 1 'Begin the MP on the rows 'Iterate until convergence or for a maximum of 10 iterations while((Istep < 11) and (non0 > 0)) non0 = 0 'find the number of elements in each row for each i in rowList L=0 for each rec in theVtab if (theVtab.ReturnValue(theData,rec).IsNull)then continue elseif (theVtab.ReturnValue(theRow,rec)=i) then L=L+1 end end 'find the elements of each row and sort in ascending 'order theBitmap = theVtab.GetSelection rAlias = theRow.GetAlias.AsString dAlias = theData.GetAlias.AsString expr = "((["+rAlias+"] = "+i.AsString+")and(["+dAlias+"].IsNull = False))" theVtab.Query(expr,theBitmap,#VTAB_SELTYPE_NEW) theVtab.UpdateSelection theTable.Sort(resid,false) theTable.PromoteSelection 'find the row median (in theTable, the first record is row 0) 'ignore any empty rows if (L =0) then continue elseif (L mod 2 = 1) then medrec = theTable.ConvertRowToRecord((L-1)/2) eff = theVtab.ReturnValue(resid,medrec) else arec = theTable.ConvertRowToRecord((L/2)-1) a = theVtab.ReturnValue(resid,arec) brec = theTable.ConvertRowToRecord(L/2) b = theVtab.ReturnValue(resid,brec) eff = (a+b)/2 end 'add the median(eff) to re and subtract from resid for each rec in theVtab if ((theVtab.ReturnValue(theRow,rec) = i) and (colList.FindByValue(theVtab.ReturnValue(theCol,rec))> -1)) then reValue = theVtab.ReturnValue(re,rec) theVtab.SetValueNumber(re,rec,(reValue+eff)) if (theVtab.ReturnValue(theData,rec).IsNull = False) then residVal = theVtab.ReturnValue(resid,rec) theVtab.SetValueNumber(resid,rec,(residVal-eff)) end end end 'check to see if the effect is greater than 0 (with a tolerance of 0.5) if ((eff > 0.5) or (eff < -0.5)) then non0 = non0 + 1 end end 'Continue the MP on the columns 'find the number of elements in each col for each i in colList L=0 for each rec in theVtab if (theVtab.ReturnValue(theData,rec).IsNull)then continue elseif (theVtab.ReturnValue(theCol,rec)=i) then L=L+1 end end 'find the elements of each col and sort in ascending 'order theBitmap = theVtab.GetSelection cAlias = theCol.GetAlias.AsString dAlias = theData.GetAlias.AsString expr = "((["+cAlias+"] = "+i.AsString+")and(["+dAlias+"].IsNull = False))" theVtab.Query(expr,theBitmap,#VTAB_SELTYPE_NEW) theVtab.UpdateSelection theTable.Sort(resid,false) theTable.PromoteSelection 'find the col median (in theTable, the first record is row 0) 'ignore any empty col if (L = 0) then continue elseif (L mod 2 = 1) then medrec = theTable.ConvertRowToRecord((L-1)/2) eff = theVtab.ReturnValue(resid,medrec) else arec = theTable.ConvertRowToRecord((L/2)-1) a = theVtab.ReturnValue(resid,arec) brec = theTable.ConvertRowToRecord(L/2) b = theVtab.ReturnValue(resid,brec) eff = (a+b)/2 end 'add the median(eff) to ce and subtract from resid for each rec in theVtab if ((theVtab.ReturnValue(theCol,rec) = i) and (rowList.FindByValue(theVtab.ReturnValue(theRow,rec))> -1)) then ceValue = theVtab.ReturnValue(ce,rec) theVtab.SetValueNumber(ce,rec,(ceValue+eff)) if (theVtab.ReturnValue(theData,rec).IsNull = False) then residVal = theVtab.ReturnValue(resid,rec) theVtab.SetValueNumber(resid,rec,(residVal-eff)) end end end 'check to see if the effect is greater than 0 (with a tolerance of 0.5) if ((eff > 0.5) or (eff < -0.5)) then non0 = non0 + 1 end end Istep = Istep + 1 if(Istep = 11) then MsgBox.Info("Algorithm did not converge in 10 iterations","Nonconvergence") MsgBox.Info("Estimates from last iteration will be used","Estimates") end end 'unselect any selected records theTable.GetVTab.GetSelection.ClearAll theTable.GetVTab.UpdateSelection 'find the medians of the row and col effects and 'combine them for the all effect 'find the row median fld = theVtab.FindField(theRowName) dat = theVtab.FindField("RowEffects") newVTab = theVtab.Summarize("row.sum".AsFileName,dBase,fld,{dat}, {#VTAB_SUMMARY_FIRST}) if (newVtab.IsEditable = False) then newVtab.StartEditingWithRecovery end datFld = newVTab.FindField("First_RowEffects").SetAlias("RowEffects") datFld = newVTab.FindField("RowEffects") for each rec in newVtab if (newVtab.ReturnValue(datFld,rec).IsNull) then newVtab.RemoveRecord(rec) end end newTable = Table.Make(newVTab) newTable.GetWin.Open newTable.Sort(datFld,false) if (nr mod 2 = 1) then medrec = newTable.ConvertRowToRecord((nr-1)/2) medr = newVTab.ReturnValue(datFld,medrec) else arec = newTable.ConvertRowToRecord((nr/2)-1) a = newVTab.ReturnValue(datFld,arec) brec = newTable.ConvertRowToRecord(nr/2) b = newVTab.ReturnValue(datFld,brec) medr = (a+b)/2 end 'Find the col median fld = theVtab.FindField(theColName) dat = theVtab.FindField("ColEffects") newVTab = theVtab.Summarize("col.sum".AsFileName,dBase,fld,{dat}, {#VTAB_SUMMARY_FIRST}) if (newVtab.IsEditable = False) then newVtab.StartEditingWithRecovery end datFld = newVTab.FindField("First_ColEffects").SetAlias("ColEffects") datFld = newVTab.FindField("ColEffects") for each rec in newVtab if (newVtab.ReturnValue(datFld,rec).IsNull) then newVtab.RemoveRecord(rec) end end newTable = Table.Make(newVTab) newTable.GetWin.Open newTable.Sort(datFld,false) if (nc mod 2 = 1) then medrec = newTable.ConvertRowToRecord((nc-1)/2) medc = newVTab.ReturnValue(datFld,medrec) else arec = newTable.ConvertRowToRecord((nc/2)-1) a = newVTab.ReturnValue(datFld,arec) brec = newTable.ConvertRowToRecord(nc/2) b = newVTab.ReturnValue(datFld,brec) medc = (a+b)/2 end 'subtract the row and col medians from the rowEffects and colEffects, 'respectively and add them to the allEffect for each rec in theVtab if ((rowList.FindByValue(theVtab.ReturnValue(theRow,rec))> -1) and (colList.FindByValue(theVtab.ReturnValue(theCol,rec))> -1)) then reValue = theVtab.ReturnValue(re,rec) ceValue = theVtab.ReturnValue(ce,rec) allValue = medr + medc theVtab.SetValueNumber(re,rec,(reValue-medr)) theVtab.SetValueNumber(ce,rec,(ceValue-medc)) theVtab.SetValueNumber(all,rec,allValue) end end 'unselect any selected records theTable.GetVTab.GetSelection.ClearAll theTable.GetVTab.UpdateSelection 'Save the table with the median polish data to a file 'theVtab.SaveEditsAs("mp_data.dbf".AsFileName) 'MsgBox.Info("The table including the columns from Median Polishing"++ ' "will be saved in the file mp_data.dbf","Data location")