TableData.cpp
上传用户:szb0815
上传日期:2007-06-13
资源大小:338k
文件大小:27k
源码类别:

生物技术

开发平台:

C++ Builder

  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5. #pragma hdrstop
  6. #include "TableData.h"
  7. #include "MyUtils.h"
  8. //---------------------------------------------------------------------------
  9. #pragma package(smart_init)
  10. AnsiString NextString(AnsiString* String)
  11. {
  12.     AnsiString Field;
  13.     int delim = (*String).LastDelimiter("t");
  14.     if (delim != 0)
  15.     {
  16.         Field = (*String).SubString(delim+1,(*String).Length()-delim);
  17.         (*String) =  (*String).SubString(0,delim-1);
  18.     }
  19.     else
  20.     {
  21.         Field = (*String);
  22.         (*String) =  (*String).SubString(0,0);
  23.     }
  24.     if ((Field.Length() == 0) && (delim == 0) )
  25.     {
  26.         return AnsiString("DONE");
  27.     }
  28.     else
  29.     {
  30.         return Field;
  31.     }
  32. }
  33. void __fastcall SplitString(AnsiString *String, TStringList *List)
  34. {
  35.     AnsiString Field;
  36.     List->Clear();
  37.     while ((Field = NextString(String)) != "DONE")
  38.     {
  39.           List->Insert(0,Field);
  40.     }
  41. }
  42. AnsiString __fastcall RowDataInfoToString(float *OutRowData, int n, TTableObjectInfo *Info)
  43. {
  44.     TFloatFormat Format = ffGeneral;
  45.     AnsiString Tmp = Info->ID + "t" + Info->Name + "t" + AnsiString(Info->Weight);
  46.     for (int i=0; i<n; i++)
  47.     {
  48.         Tmp += "t";
  49.         if (OutRowData[i] != NODATA)
  50.         {
  51.             Tmp += AnsiString(FloatToStrF(OutRowData[i],Format,2,2));
  52.         }
  53.     }
  54.     return Tmp;
  55. }
  56. AnsiString __fastcall RowDataLabelToString(float *OutRowData, int n, AnsiString Label)
  57. {
  58.     AnsiString Tmp = Label + "t" + Label;
  59.     for (int i=0; i<n; i++)
  60.     {
  61.         Tmp += "t";
  62.         if (OutRowData[i] != NODATA)
  63.         {
  64.             Tmp += AnsiString(OutRowData[i]);
  65.         }
  66.     }
  67.     return Tmp;
  68. }
  69. AnsiString __fastcall RowDataLabelsToString(float *OutRowData, int n, AnsiString IDLabel, AnsiString NameLabel)
  70. {
  71.     AnsiString Tmp = IDLabel + "t" + NameLabel;
  72.     for (int i=0; i<n; i++)
  73.     {
  74.         Tmp += "t";
  75.         if (OutRowData[i] != NODATA)
  76.         {
  77.             Tmp += AnsiString(OutRowData[i]);
  78.         }
  79.     }
  80.     return Tmp;
  81. }
  82. __fastcall TTableObjectInfo::TTableObjectInfo() : TObject()
  83. {
  84.     ID     = "";
  85.     Name   = "";
  86.     Group  = 1;
  87.     Weight = 1;
  88.     Order  = 1;
  89. }
  90. __fastcall TTableObjectInfo::~TTableObjectInfo()
  91. {
  92.     ID = "";
  93.     Name = "";
  94. }
  95. void __fastcall TTableObjectInfo::ReadFromStream(TFileStream *Stream)
  96. {
  97.     int size;
  98.     char *tempstring;
  99.     Stream->Read(&size,sizeof(int));
  100.     tempstring = new char[size];
  101.     Stream->Read(tempstring,size*sizeof(char));
  102.     ID = AnsiString(tempstring).SubString(1,size);
  103.     delete tempstring;
  104.     Stream->Read(&size,sizeof(int));
  105.     tempstring = new char[size];
  106.     Stream->Read(tempstring,size*sizeof(char));
  107.     Name = AnsiString(tempstring).SubString(1,size);
  108.     delete tempstring;
  109.     Stream->Read(&Group,sizeof(Group));
  110.     Stream->Read(&Weight,sizeof(Group));
  111.     Stream->Read(&Order,sizeof(Group));
  112. }
  113. void __fastcall TTableObjectInfo::WriteToStream(TFileStream *Stream)
  114. {
  115.     int size;
  116.     char* tempstring;
  117.     tempstring = ID.c_str();
  118.     size = ID.Length();
  119.     Stream->Write(&size,sizeof(size));
  120.     Stream->Write(tempstring,size*sizeof(char));
  121.     tempstring = Name.c_str();
  122.     size = Name.Length();
  123.     Stream->Write(&size,sizeof(size));
  124.     Stream->Write(tempstring,size*sizeof(char));
  125.     Stream->Write(&Group,sizeof(Group));
  126.     Stream->Write(&Weight,sizeof(Group));
  127.     Stream->Write(&Order,sizeof(Group));
  128. }
  129. __fastcall TTableData::TTableData() : TObject()
  130. {                                                                                  
  131. }
  132. __fastcall TTableData::~TTableData()
  133. {
  134.     for (int Row=0;Row<Rows;Row++)
  135.     {
  136.         try
  137.         {
  138.             delete Data[Row];
  139.         }
  140.         catch (Exception &E)
  141.         {
  142.         }
  143.         try
  144.         {
  145.             delete RowInfo[Row];
  146.         }
  147.         catch (Exception &E)
  148.         {
  149.         }
  150.     }
  151.     for (int Column=0;Column<Columns;Column++)
  152.     {
  153.         try
  154.         {
  155.             delete ColumnInfo[Column];
  156.         }
  157.         catch (Exception &E)
  158.         {
  159.         }
  160.     }
  161.     delete Data;
  162.     delete RowInfo;
  163.     delete ColumnInfo;
  164. }
  165. void __fastcall TTableData::LoadFromTabFile(AnsiString FileName)
  166. {
  167.     // Clear old Data
  168.     UpdateUser("Processing File",0);
  169.     for (int Row=0;Row<Rows;Row++)
  170.     {
  171.         delete Data[Row];
  172.         delete RowInfo[Row];
  173.     }
  174.     for (int Column=0;Column<Columns;Column++)
  175.     {
  176.         delete ColumnInfo[Column];
  177.     }
  178.     delete Data;
  179.     delete RowInfo;
  180.     delete ColumnInfo;
  181.     // Load file into TStringList
  182.     TStringList *List = new TStringList();
  183.     List->LoadFromFile(FileName);
  184.     // Create TStringList for individual lines of tab-delimited data
  185.     TStringList *LineList = new TStringList();
  186.     AnsiString Line;
  187.     //First Parse Header Line
  188.     //It is assumed that first line contains headers
  189.     Line = List->Strings[0];
  190.     SplitString(&Line,LineList);
  191.     IDType = LineList->Strings[0];
  192.     int NameIndex   = -1;
  193.     int WeightIndex = -1;
  194.     int GroupIndex  = -1;
  195.     int OrderIndex  = -1;
  196.     // Determine column positions of various gene information columns
  197.     NameIndex   = max(NameIndex,LineList->IndexOf("NAME"));
  198.     NameIndex   = max(NameIndex,LineList->IndexOf("DESC"));
  199.     NameIndex   = max(NameIndex,LineList->IndexOf("DESCRIPTION"));
  200.     WeightIndex = max(WeightIndex,LineList->IndexOf("WEIGHT"));
  201.     WeightIndex = max(WeightIndex,LineList->IndexOf("GWEIGHT"));
  202.     GroupIndex  = max(GroupIndex,LineList->IndexOf("GROUP"));
  203.     GroupIndex  = max(GroupIndex,LineList->IndexOf("GROUP"));
  204.     OrderIndex  = max(OrderIndex,LineList->IndexOf("ORDER"));
  205.     OrderIndex  = max(OrderIndex,LineList->IndexOf("GORDER"));
  206.     // Assume all other columns are data columns
  207.     bool* ColumnIsData = new bool[LineList->Count];
  208.     for (int Column=0; Column<LineList->Count; Column++)
  209.     {
  210.         ColumnIsData[Column] = true;
  211.     }
  212.     // Start out assuming number of data columns = number of columns in header
  213.     Columns = LineList->Count;
  214.     // The first columns must be ID
  215.     ColumnIsData[0] = false;
  216.     Columns--;
  217.     //Now check the rest of the columns
  218.     if (NameIndex > -1)
  219.     {
  220.        ColumnIsData[NameIndex] = false;
  221.        Columns--;
  222.     }
  223.     if (WeightIndex > -1)
  224.     {
  225.        ColumnIsData[WeightIndex] = false;
  226.        Columns--;
  227.     }
  228.     if (GroupIndex > -1)
  229.     {
  230.        ColumnIsData[GroupIndex] = false;
  231.        Columns--;
  232.     }
  233.     if (OrderIndex > -1)
  234.     {
  235.        ColumnIsData[OrderIndex] = false;
  236.        Columns--;
  237.     }
  238.     // OK Columns is the number of data columns
  239.     ColumnInfo = new TTableObjectInfo*[Columns];
  240.     int ColumnIndex = 0;
  241.     int* InColumn = new int[Columns];
  242.     for (int Column=0; Column<LineList->Count; Column++)
  243.     {
  244.         if (ColumnIsData[Column])
  245.         {
  246.            ColumnInfo[ColumnIndex] = new TTableObjectInfo();
  247.            ColumnInfo[ColumnIndex]->ID = LineList->Strings[Column];
  248.            InColumn[ColumnIndex] = Column;
  249.            ColumnIndex++;
  250.         }
  251.     }
  252.     bool* RowIsData = new bool[List->Count];
  253.     for (int Row=0; Row<List->Count; Row++)
  254.     {
  255.         RowIsData[Row] = true;
  256.     }
  257.     Rows = List->Count;
  258.     // Subtract 1 for header
  259.     RowIsData[0] = false;
  260.     Rows--;
  261.     // Now do a first pass to figure out which rows have accessory info about
  262.     // the columns. If they have such info, load it into ColumnInfo
  263.     // Limit search to the first 10 rows
  264.     for (int Row=1; Row<10; Row++)
  265.     {
  266.         Line = List->Strings[Row];
  267.         SplitString(&Line,LineList);
  268.         // Rows should have a special key in the first column to indicate the
  269.         // presence of accessory information about columns
  270.         // WEIGHT or EWEIGHT indicate presence of user-defined weight information
  271.         // for columns, see manual for details
  272.         if  ( (LineList->Strings[0] == "WEIGHT") || (LineList->Strings[0] == "EWEIGHT") )
  273.         {
  274.             Rows--;
  275.             RowIsData[Row] = false;
  276.             for (int Column=0; Column<Columns; Column++)
  277.             {
  278.                 try
  279.                 {
  280.                    double Weight = LineList->Strings[InColumn[Column]].ToDouble();
  281.                    ColumnInfo[Column]->Weight = Weight;
  282.                 }
  283.                 catch (Exception &E)
  284.                 {
  285.                 }
  286.             }
  287.         }
  288.         // ORDER or EORDER indicate presence of user-defined order information
  289.         // for columns, see manual for details
  290.         else if ( (LineList->Strings[0] == "ORDER") || (LineList->Strings[0] == "EORDER") )
  291.         {
  292.             Rows--;
  293.             RowIsData[Row] = false;
  294.             for (int Column=0; Column<Columns; Column++)
  295.             {
  296.                 try
  297.                 {
  298.                    double Order = LineList->Strings[InColumn[Column]].ToDouble();
  299.                    ColumnInfo[Column]->Order = Order;
  300.                 }
  301.                 catch (Exception &E)
  302.                 {
  303.                 }
  304.             }
  305.         }
  306.         // GROUP or EGROUP indicate presence of user-defined group information
  307.         // for columns, see manual for details
  308.         else if ( (LineList->Strings[0] == "GROUP") || (LineList->Strings[0] == "EGROUP") )
  309.         {
  310.             Rows--;
  311.             RowIsData[Row] = false;
  312.             for (int Column=0; Column<Columns; Column++)
  313.             {
  314.                 try
  315.                 {
  316.                    int Group = LineList->Strings[InColumn[Column]].ToInt();
  317.                    ColumnInfo[Column]->Group = Group;
  318.                 }
  319.                 catch (Exception &E)
  320.                 {
  321.                 }
  322.             }
  323.         }
  324.         // NAME indicate presence of user-defined name for columns
  325.         else if ( (LineList->Strings[0] == "NAME") )
  326.         {
  327.             Rows--;
  328.             RowIsData[Row] = false;
  329.             for (int Column=0; Column<Columns; Column++)
  330.             {
  331.                 try
  332.                 {
  333.                    ColumnInfo[Column]->Name = LineList->Strings[InColumn[Column]];
  334.                 }
  335.                 catch (Exception &E)
  336.                 {
  337.                 }
  338.             }
  339.         }
  340.     }
  341.     // Rows should now be the number of data rows in the file
  342.     // Allocate memory for Data and RowInfo and initialize values
  343.     Data    = new float*[Rows];
  344.     RowInfo = new TTableObjectInfo*[Rows];
  345.     for (int Row=0; Row<Rows; Row++)
  346.     {
  347.         RowInfo[Row] = new TTableObjectInfo();
  348.         Data[Row] = new float[Columns];
  349.         for (int Column=0; Column<Columns; Column++)
  350.         {
  351.             Data[Row][Column] = NODATA;
  352.         }
  353.     }
  354.     // Now get ready to pass through the file again to load data
  355.     int RowIndex = -1;
  356.     for (int Row=0; Row<List->Count; Row++)
  357.     {
  358.         if (RowIsData[Row] == true)
  359.         {
  360.            RowIndex++;
  361.            UpdateUser("Loading Row " + AnsiString(RowIndex+1) + " of " + AnsiString(Rows),1);
  362.            Line = List->Strings[Row];
  363.            SplitString(&Line,LineList);
  364.            RowInfo[RowIndex]->ID = LineList->Strings[0];
  365.            // If any of the columns represent accessory information for the
  366.            // rows, get these values and store in RowInfo
  367.            if (NameIndex > 0)
  368.            {
  369.               try
  370.               {
  371.                  AnsiString Name = LineList->Strings[NameIndex];
  372.                  RowInfo[RowIndex]->Name = Name;
  373.               }
  374.               catch (Exception &E)
  375.               {
  376.               }
  377.            }
  378.            if (WeightIndex > 0)
  379.            {
  380.               try
  381.               {
  382.                  double Weight = LineList->Strings[WeightIndex].ToDouble();
  383.                  RowInfo[RowIndex]->Weight = Weight;
  384.               }
  385.               catch (Exception &E)
  386.               {
  387.               }
  388.            }
  389.            if (GroupIndex > 0)
  390.            {
  391.               try
  392.               {
  393.                  int Group = LineList->Strings[GroupIndex].ToInt();
  394.                  RowInfo[RowIndex]->Group = Group;
  395.               }
  396.               catch (Exception &E)
  397.               {
  398.               }
  399.            }
  400.            if (OrderIndex > 0)
  401.            {
  402.               try
  403.               {
  404.                  double Order = LineList->Strings[OrderIndex].ToDouble();
  405.                  RowInfo[RowIndex]->Order = Order;
  406.               }
  407.               catch (Exception &E)
  408.               {
  409.               }
  410.            }
  411.            // Now get the data
  412.            for (int Column=0; Column<Columns; Column++)
  413.            {
  414.                try
  415.                {
  416.                    if (InColumn[Column] < LineList->Count)
  417.                    {
  418.                        if (LineList->Strings[InColumn[Column]].Length() > 0)
  419.                        {
  420.                        // should throw an exception here if there was any
  421.                        // problem getting the data from the appropriate string
  422.                        // this will include conversion errors and access errors
  423.                        // if there are not enough strings in the list
  424.                            float Val = LineList->Strings[InColumn[Column]].ToDouble();
  425.                        // if we get this far then store Val in the appropriate
  426.                        // place in the Data matrix
  427.                            Data[RowIndex][Column] = Val;
  428.                        }
  429.                    }
  430.                }
  431.                catch (Exception &E)
  432.                {
  433.                }
  434.            }
  435.         }
  436.     }
  437.     delete List;
  438.     delete LineList;
  439.     delete RowIsData;
  440.     delete ColumnIsData;
  441.     delete InColumn;
  442. }
  443. /*  SaveToTableFile
  444.     Borland C++ Builder specific routing to save to tab-delmited text file
  445. */
  446. void __fastcall TTableData::SaveToTabFile(AnsiString FileName)
  447. {
  448.     TStringList *OutList = new TStringList();
  449.     OutList->Add(RawHeader());
  450.     for (int row=0; row<Rows; row++)
  451.     {
  452.         OutList->Add(RawRowString(row));
  453.     }
  454.     OutList->SaveToFile(FileName);
  455. }
  456. void __fastcall TTableData::SaveToBinaryFile(AnsiString FileName)
  457. {
  458.     UpdateUser("Processing File",0);
  459.     TFileStream *BinaryFile = new TFileStream(FileName, fmCreate);
  460.     BinaryFile->Position = 0;
  461.     
  462.     char Header[6] = "BTD1.0";
  463.     BinaryFile->Write(&Header,sizeof(Header));
  464.     //Now write basic info
  465.     int size;
  466.     char* tempstring;
  467.     tempstring = IDType.c_str();
  468.     size = IDType.Length();
  469.     BinaryFile->Write(&size,sizeof(size));
  470.     BinaryFile->Write(tempstring,size*sizeof(char));
  471.     BinaryFile->Write(&Rows,sizeof(Rows));
  472.     BinaryFile->Write(&Columns,sizeof(Columns));
  473.     for (int row=0; row<Rows; row++)
  474.     {
  475.         RowInfo[row]->WriteToStream(BinaryFile);
  476.     }
  477.     for (int column=0; column<Columns; column++)
  478.     {
  479.         ColumnInfo[column]->WriteToStream(BinaryFile);
  480.     }
  481.     for (int row=0; row<Rows; row++)
  482.     {
  483.         BinaryFile->Write(Data[row],Columns*sizeof(float));
  484.     }
  485.     delete BinaryFile;
  486. }
  487. void __fastcall TTableData::ReadFromBinaryFile(AnsiString FileName)
  488. {
  489.     UpdateUser("Loading Binary File",0);
  490.     // Clean up
  491.     for (int Row=0;Row<Rows;Row++)
  492.     {
  493.         delete Data[Row];
  494.         delete RowInfo[Row];
  495.     }
  496.     for (int Column=0;Column<Columns;Column++)
  497.     {
  498.         delete ColumnInfo[Column];
  499.     }
  500.     delete Data;
  501.     delete RowInfo;
  502.     delete ColumnInfo;
  503.     TFileStream *BinaryFile = new TFileStream(FileName, fmOpenRead);
  504.     BinaryFile->Position = 0;
  505.     char Header[6];
  506.     BinaryFile->Read(&Header,sizeof(Header));
  507.     AnsiString AHeader = AnsiString(Header).SubString(1,6);
  508.     if (AHeader == AnsiString("BTD1.0"))
  509.     {
  510.         int size;
  511.         char *tempstring;
  512.         BinaryFile->Read(&size,sizeof(int));
  513.         tempstring = new char[size];
  514.         BinaryFile->Read(tempstring,size*sizeof(char));
  515.         IDType = AnsiString(tempstring).SubString(1,size);
  516.         delete tempstring;
  517.         BinaryFile->Read(&Rows,sizeof(Rows));
  518.         BinaryFile->Read(&Columns,sizeof(Columns));
  519.         RowInfo = new TTableObjectInfo*[Rows];
  520.         for (int row=0; row<Rows; row++)
  521.         {
  522.             RowInfo[row] = new TTableObjectInfo();
  523.             RowInfo[row]->ReadFromStream(BinaryFile);
  524.         }
  525.         ColumnInfo = new TTableObjectInfo*[Columns];
  526.         for (int col=0; col<Columns; col++)
  527.         {
  528.             ColumnInfo[col] = new TTableObjectInfo();
  529.             ColumnInfo[col]->ReadFromStream(BinaryFile);
  530.         }
  531.         Data    = new float*[Rows];
  532.         for (int row=0; row<Rows; row++)
  533.         {
  534.             UpdateUser("Loading Row " + AnsiString(row) + " of " + AnsiString(Rows),1);
  535.             Data[row] = new float[Columns];
  536.             BinaryFile->Read(Data[row],Columns*sizeof(float));
  537.         }
  538.     }
  539.     delete BinaryFile;
  540. }
  541. void __fastcall TTableData::CopyFrom(TTableData *CopyData)
  542. {
  543.     // Clear old Data
  544.     for (int Row=0;Row<Rows;Row++)
  545.     {
  546.         delete Data[Row];
  547.         delete RowInfo[Row];
  548.     }
  549.     for (int Column=0;Column<Columns;Column++)
  550.     {
  551.         delete ColumnInfo[Column];
  552.     }
  553.     delete Data;
  554.     delete RowInfo;
  555.     delete ColumnInfo;
  556.     Columns = CopyData->Columns;
  557.     ColumnInfo = new TTableObjectInfo*[Columns];
  558.     for (int Column=0; Column<Columns; Column++)
  559.     {
  560.         ColumnInfo[Column] = new TTableObjectInfo();
  561.         ColumnInfo[Column]->ID = CopyData->ColumnInfo[Column]->ID;
  562.     }
  563.     Rows = CopyData->Rows;
  564.     Data    = new float*[Rows];
  565.     RowInfo = new TTableObjectInfo*[Rows];
  566.     for (int Row=0; Row<Rows; Row++)
  567.     {
  568.         RowInfo[Row] = new TTableObjectInfo();
  569.         RowInfo[Row]->ID = CopyData->RowInfo[Row]->ID;
  570.         Data[Row] = new float[Columns];
  571.         for (int Column=0; Column<Columns; Column++)
  572.         {
  573.             Data[Row][Column] = CopyData->Data[Row][Column];
  574.         }
  575.     }
  576. }
  577. void __fastcall TTableData::CopyFromRowList(TTableData *CopyData, std::vector<int> List)
  578. {
  579.     // Clear old Data
  580.     for (int Row=0;Row<Rows;Row++)
  581.     {
  582.         delete Data[Row];
  583.         delete RowInfo[Row];
  584.     }
  585.     for (int Column=0;Column<Columns;Column++)
  586.     {
  587.         delete ColumnInfo[Column];
  588.     }
  589.     delete Data;
  590.     delete RowInfo;
  591.     delete ColumnInfo;
  592.     Columns = CopyData->Columns;
  593.     ColumnInfo = new TTableObjectInfo*[Columns];
  594.     for (int Column=0; Column<Columns; Column++)
  595.     {
  596.         ColumnInfo[Column] = new TTableObjectInfo();
  597.         ColumnInfo[Column]->ID = CopyData->ColumnInfo[Column]->ID;
  598.     }
  599.     Rows = List.size();
  600.     Data    = new float*[Rows];
  601.     RowInfo = new TTableObjectInfo*[Rows];
  602.     for (int Row=0; Row<Rows; Row++)
  603.     {
  604.         RowInfo[Row] = new TTableObjectInfo();
  605.         RowInfo[Row]->ID = CopyData->RowInfo[Row]->ID;
  606.         Data[Row] = new float[Columns];
  607.         for (int Column=0; Column<Columns; Column++)
  608.         {
  609.             Data[Row][Column] = CopyData->Data[List[Row]][Column];
  610.         }
  611.     }
  612. }
  613. void __fastcall TTableData::CopyTransposedFrom(TTableData *CopyData)
  614. {
  615.     // Clear old Data
  616.     for (int Row=0;Row<Rows;Row++)
  617.     {
  618.         delete Data[Row];
  619.         delete RowInfo[Row];
  620.     }
  621.     for (int Column=0;Column<Columns;Column++)
  622.     {
  623.         delete ColumnInfo[Column];
  624.     }
  625.     delete Data;
  626.     delete RowInfo;
  627.     delete ColumnInfo;
  628.     Columns = CopyData->Rows;
  629.     ColumnInfo = new TTableObjectInfo*[Columns];
  630.     for (int Column=0; Column<Columns; Column++)
  631.     {
  632.         ColumnInfo[Column] = new TTableObjectInfo();
  633.         ColumnInfo[Column]->ID = CopyData->RowInfo[Column]->ID;
  634.     }
  635.     Rows = CopyData->Columns;
  636.     Data    = new float*[Rows];
  637.     RowInfo = new TTableObjectInfo*[Rows];
  638.     for (int Row=0; Row<Rows; Row++)
  639.     {
  640.         RowInfo[Row] = new TTableObjectInfo();
  641.         RowInfo[Row]->ID = CopyData->ColumnInfo[Row]->ID;
  642.         Data[Row] = new float[Columns];
  643.         for (int Column=0; Column<Columns; Column++)
  644.         {
  645.             Data[Row][Column] = CopyData->Data[Column][Row];
  646.         }
  647.     }
  648. }
  649. void __fastcall TTableData::MeanCenterRows()
  650. {
  651.     for (int row=0; row<Rows; row++)
  652.     {
  653.         float sum = 0;
  654.         int count = 0;
  655.         for (int col=0; col<Columns; col++)
  656.         {
  657.             if (Data[row][col] != NODATA)
  658.             {
  659.                 sum+=Data[row][col];
  660.                 count++;
  661.             }
  662.         }
  663.         if (count > 0)
  664.         {
  665.             sum /= count;
  666.         }
  667.         for (int col=0; col<Columns; col++)
  668.         {
  669.             if (Data[row][col] != NODATA)
  670.             {
  671.                 Data[row][col] -= sum;
  672.             }
  673.         }
  674.     }
  675. }
  676. void __fastcall TTableData::NormalizeRows()
  677. {
  678.     for (int row=0; row<Rows; row++)
  679.     {
  680.         float mag = 0;
  681.         int magcount = 0;
  682.         for (int col=0; col<Columns; col++)
  683.         {
  684.             if (Data[row][col] != NODATA)
  685.             {
  686.                 mag+=pow(Data[row][col],2.0);
  687.                 magcount++;
  688.             }
  689.         }
  690.         mag = sqrt(mag);
  691.         if (mag > 0)
  692.         {
  693.             for (int col=0; col<Columns; col++)
  694.             {
  695.                 if (Data[row][col] != NODATA)
  696.                 {
  697.                     Data[row][col] /= mag;
  698.                 }
  699.             }
  700.         }
  701.     }
  702. }
  703. /* Randomly permute data within rows. This could probably be
  704. recoded with a direct sort of Data[Row] but when I did this the first
  705. time things got really messed up */
  706. void __fastcall TTableData::PermuteInRows()
  707. {
  708.     float* randvector = fvector(1,Columns);
  709.     float *datavector = fvector(1,Columns);
  710.     for (int Row=0; Row<Rows; Row++)
  711.     {
  712.         for (int Column=0; Column<Columns; Column++)
  713.         {
  714.             randvector[Column+1] = rand();
  715.             datavector[Column+1] = Data[Row][Column];
  716.         }
  717.         sort2(Columns,randvector,datavector);
  718.         for (int Column=0; Column<Columns; Column++)
  719.         {
  720.             Data[Row][Column] = datavector[Column+1];
  721.         }
  722.     }
  723.     free_vector(randvector,1,Columns);
  724.     free_vector(datavector,1,Columns);  
  725. }
  726. void __fastcall TTableData::OrthogonalizeRow(int row, float *Vector)
  727. {
  728.         float dot = 0;
  729.         for (int col=0; col<Columns; col++)
  730.         {
  731.             if ( (Vector[col] != NODATA) && (Data[row][col] != NODATA) )
  732.             {
  733.                 dot += Vector[col] * Data[row][col];
  734.             }
  735.         }
  736.         for (int col=0; col<Columns; col++)
  737.         {
  738.             if ( (Vector[col] != NODATA) && (Data[row][col] != NODATA) )
  739.             {
  740.                 Data[row][col] -= dot * Vector[col];
  741.             }
  742.         }
  743. }
  744. /* Orthogonalize all rows relative to a given vector */
  745. void __fastcall TTableData::OrthogonalizeRows(float *Vector)
  746. {
  747.     float mag=0;
  748.     for (int col=0; col<Columns; col++)
  749.     {
  750.         if (Vector[col] != NODATA)
  751.         {
  752.             mag += pow(Vector[col],2.0);
  753.         }
  754.     }
  755.     mag = sqrt(mag);
  756.     float* NormVector = new float[Columns];
  757.     for (int col=0; col<Columns; col++)
  758.     {
  759.        NormVector[col] = Vector[col];
  760.        if ( (mag > 0) && (NormVector[col] != NODATA) )
  761.        {
  762.            NormVector[col] /= mag;
  763.        }
  764.     }
  765.     for (int row=0; row<Rows; row++)
  766.     {
  767.         OrthogonalizeRow(row,NormVector);
  768.     }
  769.     delete NormVector;
  770. }
  771. void __fastcall TTableData::OrthogonalizeRowList(float *Vector, int *List, int n)
  772. {
  773.     float mag=0;
  774.     for (int col=0; col<Columns; col++)
  775.     {
  776.         if (Vector[col] != NODATA)
  777.         {
  778.             mag += pow(Vector[col],2.0);
  779.         }
  780.     }
  781.     mag = sqrt(mag);
  782.     float* NormVector = new float[Columns];
  783.     for (int col=0; col<Columns; col++)
  784.     {
  785.        NormVector[col] = Vector[col];
  786.        if ( (mag > 0) && (NormVector[col] != NODATA) )
  787.        {
  788.            NormVector[col] /= mag;
  789.        }
  790.     }
  791.     for (int elem=0; elem<n; elem++)
  792.     {
  793.         if (List[elem] < Rows)
  794.         {
  795.             OrthogonalizeRow(List[elem],NormVector);
  796.         }
  797.     }
  798.     delete NormVector;
  799. }
  800. // This function returns a pointer to an array with data for a row
  801. float * __fastcall TTableData::RowData(int Row)
  802. {
  803.     float * Tmp = NULL;
  804.     if ( (0 <= Row) && (Row < Rows) )
  805.     {
  806.         try
  807.         {
  808.             Tmp = Data[Row];
  809.         }
  810.         catch (Exception &E)
  811.         {
  812.             Tmp = NULL;
  813.         }
  814.     }
  815.     return Tmp;
  816. }
  817. void __fastcall TTableData::RowAve(float *AveData)
  818. {
  819.     for (int col=0; col<Columns; col++)
  820.     {
  821.         AveData[col] = 0;
  822.         int k = 0;
  823.         for (int i=0; i<Rows; i++)
  824.         {
  825.             if (Data[i][col] != NODATA)
  826.             {
  827.                 AveData[col] += Data[i][col];
  828.                 k++;
  829.             }
  830.         }
  831.         if (k > 0)
  832.         {
  833.             AveData[col] /= k;
  834.         }
  835.     }
  836. }
  837. void __fastcall TTableData::RowListAve(int *List, int n, float *AveData)
  838. {
  839.     for (int col=0; col<Columns; col++)
  840.     {
  841.         AveData[col] = 0;
  842.         int k = 0;
  843.         for (int i=0; i<n; i++)
  844.         {
  845.             if (Data[List[i]][col] != NODATA)
  846.             {
  847.                 AveData[col] += Data[List[i]][col];
  848.                 k++;
  849.             }
  850.         }
  851.         if (k > 0)
  852.         {
  853.             AveData[col] /= k;
  854.         }
  855.     }
  856. }
  857. float __fastcall TTableData::Variance()
  858. {
  859.     int k=0;
  860.     double sum2 = 0;
  861.     for (int col=0; col<Columns; col++)
  862.     {
  863.         for (int row=0; row<Rows; row++)
  864.         {
  865.             if (Data[row][col] != NODATA)
  866.             {
  867.                 sum2 += pow(Data[row][col],2.0);
  868.                 k++;
  869.             }
  870.         }
  871.     }
  872.     if (k>0)
  873.     {
  874.         return (sqrt(sum2/k));
  875.     }
  876.     else
  877.     {
  878.         return 0;
  879.     }
  880. }
  881. std::vector<int> __fastcall TTableData::GroupList(int Group)
  882. {
  883.     std::vector<int> List;
  884.     for (int row=0; row<Rows; row++)
  885.     {
  886.         if (RowInfo[row]->Group == Group)
  887.         {
  888.             List.push_back(row);
  889.         }
  890.     }
  891.     return List;
  892. }
  893. AnsiString __fastcall TTableData::RawRowString(int Row)
  894. {
  895.     try
  896.     {
  897.         return RowDataInfoToString(Data[Row], Columns, RowInfo[Row]);
  898.     }
  899.     catch (Exception &E)
  900.     {
  901.         return "";
  902.     }
  903. }
  904. AnsiString __fastcall TTableData::RawHeader()
  905. {
  906.     AnsiString Tmp = "";
  907.     Tmp = IDType + "tNAMEtGWEIGHT";
  908.     for (int Col=0; Col<Columns; Col++)
  909.     {
  910.         Tmp += "t" + ColumnInfo[Col]->ID;
  911.     }
  912.     return Tmp;
  913. }