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

生物技术

开发平台:

C++ Builder

  1. /*
  2. Software and source code Copyright (C) 1998-2000 Stanford University
  3. Written by Michael Eisen (eisen@genome.stanford.edu)
  4. This software is copyright under the following conditions:
  5. Permission to use, copy, and modify this software and its documentation
  6. is hereby granted to all academic and not-for-profit institutions
  7. without fee, provided that the above copyright notice and this permission
  8. notice appear in all copies of the software and related documentation.
  9. Permission to distribute the software or modified or extended versions
  10. thereof on a not-for-profit basis is explicitly granted, under the above
  11. conditions. However, the right to use this software in conjunction with
  12. for profit activities, and the right to distribute the software or modified or
  13. extended versions thereof for profit are *NOT* granted except by prior
  14. arrangement and written consent of the copyright holders.
  15. Use of this source code constitutes an agreement not to criticize, in any
  16. way, the code-writing style of the author, including any statements regarding
  17. the extent of documentation and comments present.
  18. The software is provided "AS-IS" and without warranty of ank kind, express,
  19. implied or otherwise, including without limitation, any warranty of
  20. merchantability or fitness for a particular purpose.
  21. In no event shall Stanford University or the authors be liable for any special,
  22. incudental, indirect or consequential damages of any kind, or any damages
  23. whatsoever resulting from loss of use, data or profits, whether or not
  24. advised of the possibility of damage, and on any theory of liability,
  25. arising out of or in connection with the use or performance of this software.
  26. This code was written using Borland C++ Builder 4 (Inprise Inc., www.inprise.com)
  27. and may be subject to certain additional restrictions as a result.
  28. */
  29. //---------------------------------------------------------------------------
  30. #include <vcl.h>
  31. #pragma hdrstop
  32. #include "ClusterMain.h"
  33. #include <math.h>
  34. #include <dir.h>
  35. #include "FileFormat.h"
  36. #include "ClusterAbout.h"
  37. #include "ShellApi.h"
  38. #include "NumericalRecipes.h"
  39. #include "MyUtils.h"
  40. //---------------------------------------------------------------------------
  41. #pragma package(smart_init)
  42. #pragma resource "*.dfm"
  43. /* This module contains the handling code for the main form of the program
  44. as well as most of the computational routines. This is not the most elegant
  45. way to have done this, but this software was written on the fly and did not
  46. evolve in an entirely coherent manner. I have tried to organize things
  47. logically. -MBE 2/2000 */
  48. TMainForm *MainForm;
  49. //---------------------------------------------------------------------------
  50. //---------------------------------------------------------------------------
  51. /* A node class TNode is defined here. This was put in mostly for future
  52. versions of the program and isn't used extensively here */
  53. __fastcall TNode::TNode() : TObject()
  54. {
  55.     IsNode = false;
  56.     Child1 = NULL;
  57.     Child2 = NULL;
  58. }
  59. __fastcall TNode::~TNode()
  60. {
  61.     if (IsNode)
  62.     {
  63.        delete Child1;
  64.        delete Child2;
  65.     }
  66. }
  67. /* Constructer for main form */
  68. __fastcall TMainForm::TMainForm(TComponent* Owner)
  69.     : TForm(Owner)
  70. {
  71.     /* This allows drag-and-drop of files to work by sending all windows messages
  72.     to the handler routine AppMessage */
  73.     Application->OnMessage = AppMessage;
  74.     GeneMetricComboBox->ItemIndex = 0;
  75.     ArrayMetricComboBox->ItemIndex = 0;
  76.     /* Current version stored here; checked against master website to alter
  77.     user for updates */
  78.     AnsiString Version = "2.10";
  79.     try
  80.     {
  81.          NMHTTP1->Get("http://rana.stanford.edu/software/clusterversion.html");
  82.     }
  83.     catch (Exception &E)
  84.     {
  85.     }
  86.     if (Version != (AnsiString(NMHTTP1->Body)).SubString(0,Version.Length()) )
  87.     {
  88.         Caption = "Gene Cluster - Check for update at http://rana.stanford.edu/software";
  89.     }
  90.     else
  91.     {
  92.         Caption = "Gene Cluster";
  93.     }
  94.     /* Load in data from registry */
  95.     TRegistry *Registry = new TRegistry();
  96.     Registry->RootKey = HKEY_CURRENT_USER;
  97.     Registry->OpenKey("Software\Stanford\Cluster\WeightSettings",true);
  98.     try
  99.     {
  100.         GeneWeightCutoff = Registry->ReadFloat("GeneWeightCutoff");
  101.     }
  102.     catch (Exception &E)
  103.     {
  104.         GeneWeightCutoff = 0.9;
  105.     }
  106.     try
  107.     {
  108.         GeneWeightExp = Registry->ReadFloat("GeneWeightExp");
  109.     }
  110.     catch (Exception &E)
  111.     {
  112.         GeneWeightExp = 1.0;
  113.     }
  114.     try
  115.     {
  116.         ArrayWeightCutoff = Registry->ReadFloat("ArrayWeightCutoff");
  117.     }
  118.     catch (Exception &E)
  119.     {
  120.         ArrayWeightCutoff = 0.9;
  121.     }
  122.     try
  123.     {
  124.         ArrayWeightExp = Registry->ReadFloat("ArrayWeightExp");
  125.     }
  126.     catch (Exception &E)
  127.     {
  128.         ArrayWeightExp = 1.0;
  129.     }
  130.     Registry->CloseKey();
  131.     Registry->OpenKey("Software\Stanford\Cluster\Directory",true);
  132.     try
  133.     {
  134.         LoadFileDialog->InitialDir = Registry->ReadString("LastOpenDirectory");
  135.     }
  136.     catch (Exception &E)
  137.     {
  138.     }
  139.     Registry->CloseKey();
  140.     delete Registry;
  141.     GeneWeightCutoffEdit->Text = GeneWeightCutoff;
  142.     GeneWeightExpEdit->Text = GeneWeightExp;
  143.     ArrayWeightCutoffEdit->Text = ArrayWeightCutoff;
  144.     ArrayWeightExpEdit->Text = ArrayWeightExp;
  145.     DragAcceptFiles(Handle,TRUE);
  146.     Rows = 0;
  147.     Columns = 0;
  148.     /* Default Filtering Parameters */
  149.     FilterPercentVal = 80.0;
  150.     FilterPercentEdit->Text =  FilterPercentVal;
  151.     FilterSDVal = 2.0;
  152.     FilterSDEdit->Text = FilterSDVal;
  153.     FilterAbsValCount = 1;
  154.     FilterAbsValCountEdit->Text = FilterAbsValCount;
  155.     FilterAbsValVal = 2.0;
  156.     FilterAbsValEdit->Text = FilterAbsValVal;
  157.     FilterMaxMinVal = 2.0;
  158.     FilterMaxMinEdit->Text = FilterMaxMinVal;
  159.     /* Defaul SOM parameters */
  160.     SOMGenesXDim = 1;
  161.     SOMGenesYDim = 10;
  162.     SOMArraysXDim = 1;
  163.     SOMArraysYDim = 10;
  164.     SOMGenesTau  = 0.02;
  165.     SOMArraysTau = 0.02;
  166.     SOMGenesIterations = 100000;
  167.     SOMArraysIterations = 20000;
  168.     /* Default K-means parameters */
  169.     GenesK = 10;
  170.     ArraysK = 10;
  171.     GMaxKCycles = 100;
  172.     AMaxKCycles = 100;
  173. }
  174. //---------------------------------------------------------------------------
  175. void __fastcall TMainForm::FormClose(TObject *Sender, TCloseAction &Action)
  176. {
  177.     TRegistry *Registry = new TRegistry();
  178.     Registry->RootKey = HKEY_CURRENT_USER;
  179.     Registry->OpenKey("Software\Stanford\Cluster\WeightSettings",true);
  180.     Registry->WriteFloat("GeneWeightCutoff",GeneWeightCutoff);
  181.     Registry->WriteFloat("GeneWeightExp",GeneWeightExp);
  182.     Registry->WriteFloat("ArrayWeightCutoff",ArrayWeightCutoff);
  183.     Registry->WriteFloat("ArrayWeightExp",ArrayWeightExp);
  184.     Registry->CloseKey();
  185.     Registry->OpenKey("Software\Stanford\Cluster\Directory",true);
  186.     char Drive[3];
  187.     char Dir[260];
  188.     fnsplit(LoadFileDialog->FileName.c_str(),Drive,Dir,NULL,NULL);
  189.     AnsiString SaveDir = AnsiString(Drive) + AnsiString(Dir);
  190.     Registry->WriteString("LastOpenDirectory",SaveDir);
  191.     Registry->CloseKey();
  192.     delete Registry;
  193. }
  194. void __fastcall TMainForm::FormDestroy(TObject *Sender)
  195. {
  196.     int i;
  197.     for (i=0;i<2*Rows-1;i++)
  198.     {
  199.         delete GeneData[i];
  200.         delete GeneMask[i];
  201.     }
  202.     delete GeneData;
  203.     delete GeneMask;
  204.     delete Headers;
  205.     delete IsData;
  206.     delete InColumn;
  207.     delete ArrayWeight;
  208.     delete ArrayOrder;
  209.     delete UniqID;
  210.     delete GeneName;
  211.     delete GeneWeight;
  212.     delete GeneOrder;
  213.     delete Use;
  214. }
  215. /* Enable Drag-Drop */
  216. void __fastcall TMainForm::FormDragDrop(TObject *Sender, TObject *Source,
  217.       int X, int Y)
  218. {
  219. /*      int i;
  220.       i = 10;
  221.       i = 10 * 10;  */
  222. }
  223. //---------------------------------------------------------------------------
  224. void __fastcall TMainForm::FormDragOver(TObject *Sender, TObject *Source,
  225.       int X, int Y, TDragState State, bool &Accept)
  226. {
  227.        Accept = true;
  228. }
  229. //---------------------------------------------------------------------------
  230. void __fastcall TMainForm::AppMessage(tagMSG &Msg, bool &Handled)
  231. {
  232.   if (Msg.message == WM_DROPFILES)
  233.   {
  234.     char lpszFile[256];
  235.     DragQueryFile((HANDLE) Msg.wParam, 0, lpszFile, sizeof(lpszFile));
  236.     LoadFile(AnsiString(lpszFile));
  237.     Handled = true;
  238.   }
  239.   /* DragFinish((HANDLE) wParam);  */
  240.   /* for all other messages, Handled remains False so that other message handlers can respond */
  241. }
  242. /* Load in data from tab-delimited text file */
  243. void __fastcall TMainForm::LoadFileButtonClick(TObject *Sender)
  244. {
  245.     // User will select a data file (*.txt)
  246.     if (LoadFileDialog->Execute())
  247.     {
  248.         char Drive[3];
  249.         char Dir[260];
  250.         fnsplit(LoadFileDialog->FileName.c_str(),Drive,Dir,NULL,NULL);
  251.         LoadFileDialog->InitialDir = AnsiString(Drive) + AnsiString(Dir);
  252.         /* Load in the file */
  253.         LoadFile(LoadFileDialog->FileName);
  254.         /* Update buttons to reflect presence of data */
  255.         FilterResultsLabel->Visible = false;
  256.         AcceptFilterButton->Visible = false;
  257.         /* Update default SOM sizes */
  258.         SOMGenesYDim = 1 + sqrt((double)Rows);
  259.         SOMGenesYDimEdit->Text = SOMGenesYDim;
  260.         SOMArraysYDim = 1 + sqrt((double)Columns);
  261.         SOMArraysYDimEdit->Text = SOMArraysYDim;
  262.         /* Clear filtering information */
  263.         FileNameMemo->Lines->Clear();
  264.         FileNameMemo->Lines->Add(LoadFileDialog->FileName);
  265.     }
  266. }
  267. void __fastcall TMainForm::LoadFile(AnsiString FileName)
  268. {
  269.             // Clear old Data
  270.     int i,j,l;
  271.     for (i=0;i<2*Rows-1;i++)
  272.     {
  273.         delete GeneData[i];
  274.         delete GeneMask[i];
  275.         GeneName[i] = "";
  276.         UniqID[i] = "";
  277.     }
  278.     delete GeneData;
  279.     delete GeneMask;
  280.     delete Headers;
  281.     delete IsData;
  282.     delete InColumn;
  283.     delete ArrayWeight;
  284.     delete ArrayOrder;
  285.     delete UniqID;
  286.     delete GeneName;
  287.     delete GeneOrder;
  288.     delete GeneWeight;
  289.     delete Use;
  290.     // Load file into TStringList to parse it
  291.     TStringList *List = new TStringList();
  292.     try
  293.     {
  294.         List->LoadFromFile(FileName);
  295.             // Extract file root
  296.             fnsplit(FileName.c_str(),NULL,NULL,ClusterName,NULL);
  297.             // Defaul JobName is root name of cluster file
  298.             JobNameEdit->Text = ClusterName;
  299.             int index;
  300.             AnsiString Line, Field;
  301.             int NameIndex, GeneWeightIndex, GeneOrderIndex;
  302.             // This is list for individual lines of tab-delimited data
  303.             TStringList *LineList = new TStringList();
  304.             //First Parse Header Line
  305.             //It is assumed that first line contains headers
  306.             Headers = new TStringList();
  307.             Line = List->Strings[0];
  308.             while ((Field = NextString(&Line)) != "DONE")
  309.             {
  310.                 Headers->Insert(0,Field);
  311.             }
  312.             //First Column is always the UniqueID
  313.             UniqueID = Headers->Strings[0];
  314.             // Look to see if NAME/DESCRIPTION, GWEIGHT/WEIGHT, or GORDER/ORDER
  315.             // fields are present
  316.             NameIndex = max(max(Headers->IndexOf("NAME"),Headers->IndexOf("DESC")),
  317.                 Headers->IndexOf("DESCRIPTION"));
  318.             GeneWeightIndex = max(Headers->IndexOf("GWEIGHT"),Headers->IndexOf("WEIGHT"));
  319.             GeneOrderIndex  = max(Headers->IndexOf("GORDER"),Headers->IndexOf("ORDER"));
  320.             IsData = new bool[Headers->Count];
  321.             for (i=0;i<Headers->Count;i++)
  322.             {
  323.                 IsData[i] = true;
  324.             }
  325.             Columns = Headers->Count;     //Number of loaded columns
  326.             // Will decrement columns and set IsData to false for non-data columns
  327.             Columns--;                    //UniqueID Column always assumed
  328.             IsData[0] = false;
  329.             if (NameIndex > -1)
  330.             {
  331.                 Columns--;
  332.                 IsData[NameIndex] = false;
  333.             }
  334.             if (GeneWeightIndex > -1)
  335.             {
  336.                 Columns--;
  337.                 IsData[GeneWeightIndex] = false;
  338.             }
  339.             if (GeneOrderIndex > -1)
  340.             {
  341.                 Columns--;
  342.                 IsData[GeneOrderIndex] = false;
  343.             }
  344.             index = 0;  // Position in list of data columns
  345.             InColumn = new int[Columns];  // Column in Input file of each data column
  346.             for (i=0;i<Headers->Count;i++)
  347.             {
  348.                 if (IsData[i] == true)
  349.                 {
  350.                     InColumn[index] = i;
  351.                     index++;
  352.                 }
  353.             }
  354.             // Array Weight is weight for each column in clustering
  355.             // Default is 1.0
  356.             ArrayWeight = new double[2*Columns-1];  // allow for possibility of
  357.             ArrayOrder  = new double[2*Columns-1];  // clustering arrays
  358.             for (i=0;i<Columns;i++)
  359.             {
  360.                 ArrayWeight[i] = 1;
  361.                 ArrayOrder[i] = 1;
  362.             }
  363.             // Now Figure out if there is an Array Weight ROW
  364.             Rows = List->Count - 1;
  365.             int LineOffset = 1;
  366.             Line = List->Strings[1];
  367.             LineList->Clear();
  368.             while ((Field = NextString(&Line)) != "DONE")
  369.             {
  370.                 LineList->Insert(0,Field);
  371.             }
  372.             if ( (LineList->Strings[0] == "EWEIGHT") ||
  373.                 (LineList->Strings[0] == "WEIGHT") )
  374.             {
  375.                 Rows--;
  376.                 LineOffset++;
  377.                 index = 0;
  378.                 for (j=0;j<min(LineList->Count,Headers->Count);j++)
  379.                 {
  380.                     if (IsData[j] == true)
  381.                     {
  382.                         try
  383.                         {
  384.                             double Val = LineList->Strings[j].ToDouble();
  385.                             ArrayWeight[index] = Val;
  386.                         }
  387.                         catch (EConvertError &E)
  388.                         {
  389.                             ArrayWeight[index] = 0;  // Default to zero if row is
  390.                                                    // present but cell empty
  391.                         }
  392.                         index ++;
  393.                     }
  394.                 }
  395.             }
  396.             Line = List->Strings[2];
  397.             LineList->Clear();
  398.             while ((Field = NextString(&Line)) != "DONE")
  399.             {
  400.                 LineList->Insert(0,Field);
  401.             }
  402.             if ( (LineList->Strings[0] == "EORDER") ||
  403.                 (LineList->Strings[0] == "ORDER") )
  404.             {
  405.                 Rows--;
  406.                 LineOffset ++;
  407.                 index = 0;
  408.                 for (j=0;j<min(LineList->Count,Headers->Count);j++)
  409.                 {
  410.                     if (IsData[j] == true)
  411.                     {
  412.                         try
  413.                         {
  414.                             double Val = LineList->Strings[j].ToDouble();
  415.                             ArrayOrder[index] = Val;
  416.                         }
  417.                         catch (EConvertError &E)
  418.                         {
  419.                             ArrayOrder[index] = 0;  // Default to zero if row is
  420.                                                    // present but cell empty
  421.                         }
  422.                         index ++;
  423.                     }
  424.                 }
  425.             }
  426.             GeneData    = new double*[2*Rows-1];
  427.             GeneMask    = new bool*[2*Rows-1];
  428.             UniqID      = new AnsiString[2*Rows-1];
  429.             GeneName    = new AnsiString[2*Rows-1];
  430.             GeneWeight  = new double[2*Rows-1];
  431.             GeneOrder   = new double[2*Rows-1];
  432.             for (i=0;i<2*Rows-1;i++)
  433.             {
  434.                 GeneData[i] = new double[Columns];
  435.                 GeneMask[i] = new bool[Columns];
  436.                 for (j=0;j<Columns;j++)
  437.                 {
  438.                     GeneMask[i][j] = false;
  439.                 }
  440.             }
  441.             for (i=LineOffset;i<List->Count;i++)
  442.             {
  443.                 LineList->Clear();
  444.                 l = i - LineOffset;
  445.                 //Update user on status
  446.                 StatusBar1->SimpleText = "Loading Gene " + AnsiString(l + 1) + " of "
  447.                 + AnsiString(List->Count - LineOffset);
  448.                 Application->ProcessMessages();
  449.                 //Get current line
  450.                 Line = List->Strings[i];
  451.                 //Parse Line into fields
  452.                 while ((Field = NextString(&Line)) != "DONE")
  453.                 {
  454.                     LineList->Insert(0,Field);
  455.                 }
  456.                 //UniqID always columns 0
  457.                 UniqID[l] = LineList->Strings[0];
  458.                 if (NameIndex > -1)
  459.                 {
  460.                     GeneName[l] = LineList->Strings[NameIndex];
  461.                 }
  462.                 else
  463.                 {
  464.                     GeneName[l] = UniqID[l];
  465.                 }
  466.                 if (GeneWeightIndex > -1)
  467.                 {
  468.                     try
  469.                     {
  470.                         GeneWeight[l] = LineList->Strings[GeneWeightIndex].ToDouble();
  471.                     }
  472.                     catch (EConvertError &E)
  473.                     {
  474.                     }
  475.                 }
  476.                 else
  477.                 {
  478.                     GeneWeight[l] = 1.0;
  479.                 }
  480.                 if (GeneOrderIndex > -1)
  481.                 {
  482.                     try
  483.                     {
  484.                         GeneOrder[l] = LineList->Strings[GeneOrderIndex].ToDouble();
  485.                     }
  486.                     catch (EConvertError &E)
  487.                     {
  488.                     }
  489.                 }
  490.                 else
  491.                 {
  492.                     GeneOrder[l] = 1.0;
  493.                 }
  494.                 index = 0;
  495.                 for (j=0;j<min(LineList->Count,Headers->Count);j++)
  496.                 {
  497.                     if (IsData[j] == true)
  498.                     {
  499.                         if (LineList->Strings[j].Length() > 0)
  500.                         {
  501.                         try
  502.                         {
  503.                             double Val = LineList->Strings[j].ToDouble();
  504.                             GeneData[l][index] = Val;
  505.                             GeneMask[l][index] = true;
  506.                         }
  507.                         catch (EConvertError &E)
  508.                         {
  509.                         }
  510.                         }
  511.                         index ++;
  512.                     }
  513.                 }
  514.             }
  515.             delete LineList;
  516.             StatusBar1->SimpleText = "Done Loading Data";
  517.         }
  518.         catch (Exception &E)
  519.         {
  520.             Application->MessageBox("Could not Open FilenIf the file is open in another program (e.g. Excel)nClose it and try again","Could Not Open File",
  521.             MB_OK);
  522.         }
  523.         delete List;
  524. }
  525. /* Tab-delimited parsing utility for LoadFile */
  526. AnsiString TMainForm::NextString(AnsiString* String)
  527. {
  528.     AnsiString Field;
  529.     int delim = (*String).LastDelimiter("t");
  530.     if (delim != 0)
  531.     {
  532.         Field = (*String).SubString(delim+1,(*String).Length()-delim);
  533.         (*String) =  (*String).SubString(0,delim-1);
  534.     }
  535.     else
  536.     {
  537.         Field = (*String);
  538.         (*String) =  (*String).SubString(0,0);
  539.     }
  540.     if ((Field.Length() == 0) && (delim == 0) )
  541.     {
  542.         return AnsiString("DONE");
  543.     }
  544.     else
  545.     {
  546.         return Field;
  547.     }
  548. }
  549. void __fastcall TMainForm::SaveData(AnsiString FileName)
  550. {
  551.      TStringList *DataFile = new TStringList();
  552.      AnsiString OutString = "";
  553.      OutString += Headers->Strings[0] + AnsiString("t");
  554.      OutString += AnsiString("NAME") + AnsiString("t");
  555.      OutString += "GWEIGHT";
  556.      TFloatFormat Format = ffGeneral;
  557.      // Now add headers for data columns
  558.      for (int i=0;i<Columns;i++)
  559.      {
  560.          OutString += "t";
  561.          OutString += AnsiString(Headers->Strings[InColumn[i]]);
  562.      }
  563.      DataFile->Add(OutString);
  564.      {
  565.         OutString = AnsiString("EWEIGHT");
  566.         OutString += AnsiString("t");
  567.         OutString += AnsiString("t");
  568.         for (int i=0;i<Columns;i++)
  569.         {
  570.             OutString += "t" + AnsiString(ArrayWeight[i]);
  571.         }
  572.     }
  573.     DataFile->Add(OutString);
  574.     int index, colindex;
  575.     for (int i=0;i<Rows;i++)
  576.     {
  577.         index = i;
  578.         OutString = "";
  579.         OutString += AnsiString(UniqID[index]) + "t" + AnsiString(GeneName[index]);
  580.         OutString += "t" + AnsiString(GeneWeight[index]);
  581.         for (int j=0;j<Columns;j++)
  582.         {
  583.             colindex = j;
  584.             if (GeneMask[index][colindex] == true)
  585.             {
  586.                 OutString += "t" + AnsiString(FloatToStrF(GeneData[index][colindex],Format,4,2));
  587.             }
  588.             else
  589.             {
  590.                 OutString += "t";
  591.             }
  592.         }
  593.         DataFile->Add(OutString);
  594.     }
  595.     DataFile->SaveToFile(FileName);
  596.     delete DataFile;
  597. }
  598. void __fastcall TMainForm::SaveButtonClick(TObject *Sender)
  599. {
  600.     SaveDataDialog->FileName = JobNameEdit->Text + ".txt";
  601.     if (SaveDataDialog->Execute())
  602.     {
  603.         SaveData(SaveDataDialog->FileName);
  604.     }
  605. }
  606. //---------------------------------------------------------------------------
  607. /* File Format Help Button Clicked */
  608. void __fastcall TMainForm::FileHelpClick(TObject *Sender)
  609. {
  610.     FileFormatForm->Show();
  611. }
  612. /* Open Cluster Manual in Browser Window */
  613. void __fastcall TMainForm::ManualButtonClick(TObject *Sender)
  614. {
  615.     ShellExecute(Handle, "open", "http://rana.stanford.edu/software/manuals/ClusterTreeView.pdf", 0, 0, SW_SHOWNORMAL);
  616. }
  617. //---------------------------------------------------------------------------
  618. /* Filter data. Apply user selected criteria to flag (for subsequent removal)
  619. rows that fail to pass tests. Note that filters are assessed here and applied
  620. separately so the user can adjust parameters to get appropriate number
  621. of rows passing */
  622. void __fastcall TMainForm::FilterClick(TObject *Sender)
  623. {
  624.      FilterResultsLabel->Visible = false;
  625.      AcceptFilterButton->Visible = false;
  626.      /* Store results in boolean Use */
  627.      delete Use;
  628.      Use = new bool[Rows];
  629.      UseRows = 0;
  630.      for (int Row=0;Row<Rows;Row++)
  631.      {
  632.          StatusBar1->SimpleText = "Assessing Filters for Gene " + AnsiString(Row);
  633.          int Count = 0;
  634.          int CountAbs = 0;
  635.          double Sum = 0;
  636.          double Sum2 = 0;
  637.          double Min = 10000000;
  638.          double Max = -10000000;
  639.          /* Compute some row stats */
  640.          for (int Column=0;Column<Columns;Column++)
  641.          {
  642.              if (GeneMask[Row][Column])
  643.              {
  644.                 Sum += GeneData[Row][Column];
  645.                 Sum2 += pow(GeneData[Row][Column],2);
  646.                 Count ++;
  647.                 Min = min(GeneData[Row][Column],Min);
  648.                 Max = max(GeneData[Row][Column],Max);
  649.                 if (fabs(GeneData[Row][Column]) >= FilterAbsValVal)
  650.                 {
  651.                         CountAbs++;
  652.                 }
  653.              }
  654.          }
  655.          Use[Row] = true;
  656.          /* Filter based on percent values present; remove rows
  657.          with too many missing values */
  658.          if (FilterPercentCheckBox->Checked)
  659.          {
  660.                 double PercentPresent =  (double) Count / (double) Columns;
  661.                 if ( (100 * PercentPresent) < FilterPercentVal )
  662.                 {
  663.                         Use[Row] = false;
  664.                 }
  665.          }
  666.          /* Remove rows with low SD */
  667.          if (FilterSDCheckBox->Checked)
  668.          {
  669.                 if (Count > 1)
  670.                 {
  671.                         double Ave = Sum / (double) Count;
  672.                         double Arg = (Sum2 - 2 * Ave * Sum + (double) Count * pow(Ave,2))/ ((double)(Count-1));
  673.                         double SD  = sqrt(Arg);
  674.                         if (SD < FilterSDVal)
  675.                         {
  676.                                 Use[Row] = false;
  677.                         }
  678.                 }
  679.                 else
  680.                 {
  681.                         Use[Row] = false;
  682.                 }
  683.          }
  684.          /* Remove rows with too few extreme values */
  685.          if (FilterAbsValCheckBox->Checked)
  686.          {
  687.                 if (CountAbs < FilterAbsValCount)
  688.                 {
  689.                         Use[Row] = false;
  690.                 }
  691.          }
  692.          /* Remove rows with too small Max-Min */
  693.          if (FilterMaxMinCheckBox->Checked)
  694.          {
  695.                 if (Max - Min < FilterMaxMinVal)
  696.                 {
  697.                         Use[Row] = false;
  698.                 }
  699.          }
  700.          if (Use[Row])
  701.          {
  702.                 UseRows++;
  703.          }
  704.      }
  705.      FilterResultsLabel->Visible = true;
  706.      /* Tell user how many rows passed */
  707.      FilterResultsLabel->Caption = AnsiString(UseRows) + " passed out of " +
  708.         AnsiString(Rows);
  709.      AcceptFilterButton->Visible = true;
  710.      StatusBar1->SimpleText = "Done Analyzing Filters";
  711. }
  712. //---------------------------------------------------------------------------
  713. /* Accept results of last filtering */
  714. void __fastcall TMainForm::AcceptFilterButtonClick(TObject *Sender)
  715. {
  716.     AcceptFilterButton->Visible = false;
  717.     AnsiString *TempID;
  718.     AnsiString *TempName;
  719.     double *TempOrder;
  720.     double *TempWeight;
  721.     double **TempData;
  722.     bool   **TempMask;
  723.     TempID      = new AnsiString[Rows];
  724.     TempName    = new AnsiString[Rows];
  725.     TempOrder   = new double[Rows];
  726.     TempWeight  = new double[Rows];
  727.     TempData    = new double*[Rows];
  728.     TempMask    = new bool*[Rows];
  729.     for (int Row=0;Row<Rows;Row++)
  730.     {
  731.          TempData[Row] = new double[Columns];
  732.          TempMask[Row] = new bool[Columns];
  733.          for (int Column=0;Column<Columns;Column++)
  734.          {
  735.              TempData[Row][Column] = GeneData[Row][Column];
  736.              TempMask[Row][Column] = GeneMask[Row][Column];
  737.          }
  738.          TempID[Row]     = UniqID[Row];
  739.          TempName[Row]   = GeneName[Row];
  740.          TempOrder[Row]  = GeneOrder[Row];
  741.          TempWeight[Row] = GeneWeight[Row];
  742.     }
  743.     for (int Row=0;Row<Rows;Row++)
  744.     {
  745.          delete GeneData[Row];
  746.          delete GeneMask[Row];
  747.          UniqID[Row] = "";
  748.          GeneName[Row] = "";
  749.     }
  750.     delete GeneData;
  751.     delete GeneMask;
  752.     delete UniqID;
  753.     delete GeneName;
  754.     delete GeneOrder;
  755.     delete GeneWeight;
  756.     UniqID      = new AnsiString[2*UseRows-1];
  757.     GeneName    = new AnsiString[2*UseRows-1];
  758.     GeneOrder   = new double[2*UseRows-1];
  759.     GeneWeight  = new double[2*UseRows-1];
  760.     GeneData    = new double*[2*UseRows-1];
  761.     GeneMask    = new bool*[2*UseRows-1];
  762.     for (int Row=0;Row<2*UseRows-1;Row++)
  763.     {
  764.         GeneData[Row] = new double[Columns];
  765.         GeneMask[Row] = new bool[Columns];
  766.     }
  767.     int Counter = 0;
  768.     for (int Row=0;Row<Rows;Row++)
  769.     {
  770.          if (Use[Row])
  771.          {
  772.             for (int Column=0;Column<Columns;Column++)
  773.             {
  774.                 GeneData[Counter][Column] = TempData[Row][Column];
  775.                 GeneMask[Counter][Column] = TempMask[Row][Column];
  776.             }
  777.             UniqID[Counter]       = TempID[Row];
  778.             GeneName[Counter]     = TempName[Row];
  779.             GeneOrder[Counter]    = TempOrder[Row];
  780.             GeneWeight[Counter]   = TempWeight[Row];
  781.             Counter++;
  782.          }
  783.     }
  784.     for (int Row=0;Row<Rows;Row++)
  785.     {
  786.         delete TempData[Row];
  787.         delete TempMask[Row];
  788.         TempName[Row] = "";
  789.         TempID[Row] = "";
  790.     }
  791.     delete TempData;
  792.     delete TempMask;
  793.     delete TempID;
  794.     delete TempName;
  795.     delete TempOrder;
  796.     delete TempWeight;
  797.     Rows = Counter;
  798.     /* Update SOM defaults to reflect new number of rows */
  799.     SOMGenesYDim = 1 + sqrt((double)Rows);
  800.     SOMGenesYDimEdit->Text = SOMGenesYDim;
  801.     SOMArraysYDim = 1 + sqrt((double)Columns);
  802.     SOMArraysYDimEdit->Text = SOMArraysYDim;
  803. }
  804. //---------------------------------------------------------------------------
  805. //---------------------------------------------------------------------------
  806. void __fastcall TMainForm::FilterPercentEditExit(TObject *Sender)
  807. {
  808.         double TempVal = FilterPercentVal;
  809.         try
  810.         {
  811.                 FilterPercentVal = FilterPercentEdit->Text.ToDouble();
  812.         }
  813.         catch (EConvertError &E)
  814.         {
  815.                 FilterPercentVal = TempVal;
  816.                 FilterPercentEdit->Text =  FilterPercentVal;
  817.         }
  818. }
  819. //---------------------------------------------------------------------------
  820. void __fastcall TMainForm::FilterSDEditExit(TObject *Sender)
  821. {
  822.         double TempVal = FilterSDVal;
  823.         try
  824.         {
  825.                 FilterSDVal = FilterSDEdit->Text.ToDouble();
  826.         }
  827.         catch (EConvertError &E)
  828.         {
  829.                 FilterSDVal = TempVal;
  830.                 FilterSDEdit->Text =  FilterSDVal;
  831.         }
  832. }
  833. //---------------------------------------------------------------------------
  834. void __fastcall TMainForm::FilterAbsValCountEditExit(TObject *Sender)
  835. {
  836.         int TempVal = FilterAbsValCount;
  837.         try
  838.         {
  839.                 FilterAbsValCount = FilterAbsValCountEdit->Text.ToDouble();
  840.         }
  841.         catch (EConvertError &E)
  842.         {
  843.                 FilterAbsValCount = TempVal;
  844.                 FilterAbsValCountEdit->Text =  FilterAbsValCount;
  845.         }
  846. }
  847. //---------------------------------------------------------------------------
  848. void __fastcall TMainForm::FilterAbsValEditExit(TObject *Sender)
  849. {
  850.         double TempVal = FilterAbsValVal;
  851.         try
  852.         {
  853.                 FilterAbsValVal = FilterAbsValEdit->Text.ToDouble();
  854.         }
  855.         catch (EConvertError &E)
  856.         {
  857.                 FilterAbsValVal = TempVal;
  858.                 FilterAbsValEdit->Text =  FilterAbsValVal;
  859.         }
  860. }
  861. //---------------------------------------------------------------------------
  862. void __fastcall TMainForm::FilterMaxMinEditExit(TObject *Sender)
  863. {
  864.         double TempVal = FilterMaxMinVal;
  865.         try
  866.         {
  867.                 FilterMaxMinVal = FilterMaxMinEdit->Text.ToDouble();
  868.         }
  869.         catch (EConvertError &E)
  870.         {
  871.                 FilterMaxMinVal = TempVal;
  872.                 FilterMaxMinEdit->Text =  FilterMaxMinVal;
  873.         }
  874. }
  875. //---------------------------------------------------------------------------
  876. /* Adjust data values in various ways */
  877. void __fastcall TMainForm::AdjustDataButtonClick(TObject *Sender)
  878. {
  879.     for (int Row=0; Row<Rows; Row++)
  880.     {
  881.         StatusBar1->SimpleText = "Adjusting Data for Gene " + AnsiString(Row+1)
  882.             + " of " + AnsiString(Rows);
  883.         float *DataPoints = vector(1,Columns);
  884.         int CountDataPoints = 0;
  885.         float DataSum = 0;
  886.         for (int Column=0;Column<Columns;Column++)
  887.         {
  888.             if ( LogTransformCheckBox->Checked && GeneMask[Row][Column] )
  889.             {
  890.                 if (GeneData[Row][Column] > 0)
  891.                 {
  892.                     GeneData[Row][Column] = log(GeneData[Row][Column])/log(2);
  893.                 }
  894.                 else
  895.                 {
  896.                     GeneMask[Row][Column] = 0;
  897.                 }
  898.             }
  899.             if (GeneMask[Row][Column])
  900.             {
  901.                 CountDataPoints++;
  902.                 DataPoints[CountDataPoints] = GeneData[Row][Column];
  903.                 DataSum += GeneData[Row][Column];
  904.             }
  905.         }
  906.         if (MeanCenterGenesCheckBox->Checked)
  907.         {
  908.             if (CountDataPoints > 0)
  909.             {
  910.                 float DataMean = DataSum / (float) CountDataPoints;
  911.                 for (int Column=0;Column<Columns;Column++)
  912.                 {
  913.                     GeneData[Row][Column] -= DataMean;
  914.                 }
  915.             }
  916.         }
  917.         else if (MedianCenterGenesCheckBox->Checked)
  918.         {
  919.             float Median;
  920.             if (CountDataPoints > 1)
  921.             {
  922.                 if ( (CountDataPoints % 2) == 0)
  923.                 {
  924.                     Median = 0.5 * ( select((CountDataPoints/2),CountDataPoints,DataPoints)
  925.                     + select(1+(CountDataPoints/2),CountDataPoints,DataPoints));
  926.                 }
  927.                 else
  928.                 {
  929.                     Median = select(((CountDataPoints+1)/2),CountDataPoints,DataPoints);
  930.                 }
  931.             }
  932.             else if (CountDataPoints == 1)
  933.             {
  934.                 Median = DataPoints[0];
  935.             }
  936.             for (int Column=0;Column<Columns;Column++)
  937.             {
  938.                 if (GeneMask[Row][Column])
  939.                 {
  940.                     GeneData[Row][Column] -= Median;
  941.                 }
  942.             }
  943.         }
  944.         if (NormalizeGenesCheckBox->Checked)
  945.         {
  946.             float DataSum2 = 0;
  947.             for (int Column=0;Column<Columns;Column++)
  948.             {
  949.                 if (GeneMask[Row][Column])
  950.                 {
  951.                     DataSum2 += pow(GeneData[Row][Column],2);
  952.                 }
  953.             }
  954.             float DataMag = sqrt(DataSum2);
  955.             if (DataMag > 0)
  956.             {
  957.                 for (int Column=0;Column<Columns;Column++)
  958.                 {
  959.                     if (GeneMask[Row][Column])
  960.                     {
  961.                         GeneData[Row][Column] /= DataMag;
  962.                     }
  963.                 }
  964.             }
  965.         }
  966.         free_vector(DataPoints,1,Columns);
  967.      }
  968.     for (int Column=0; Column<Columns; Column++)
  969.     {
  970.         StatusBar1->SimpleText = "Adjusting Data for Sample " + AnsiString(Column+1)
  971.             + " of " + AnsiString(Columns);
  972.         float *DataPoints = vector(1,Rows);
  973.         int CountDataPoints = 0;
  974.         float DataSum = 0;
  975.         for (int Row=0;Row<Rows;Row++)
  976.         {
  977.             if (GeneMask[Row][Column])
  978.             {
  979.                 CountDataPoints++;
  980.                 DataPoints[CountDataPoints] = GeneData[Row][Column];
  981.                 DataSum += GeneData[Row][Column];
  982.             }
  983.         }
  984.         if (MeanCenterArraysCheckBox->Checked)
  985.         {
  986.             if (CountDataPoints > 0)
  987.             {
  988.                 float DataMean = DataSum / (float) CountDataPoints;
  989.                 for (int Row=0;Row<Rows;Row++)
  990.                 {
  991.                     GeneData[Row][Column] -= DataMean;
  992.                 }
  993.             }
  994.         }
  995.         else if (MedianCenterArraysCheckBox->Checked)
  996.         {
  997.             float Median;
  998.             if (CountDataPoints > 1)
  999.             {
  1000.                 if ( (CountDataPoints % 2) == 0)
  1001.                 {
  1002.                     Median = 0.5 * ( select((CountDataPoints/2),CountDataPoints,DataPoints)
  1003.                     + select(1+(CountDataPoints/2),CountDataPoints,DataPoints));
  1004.                 }
  1005.                 else
  1006.                 {
  1007.                     Median = select(((CountDataPoints+1)/2),CountDataPoints,DataPoints);
  1008.                 }
  1009.             }
  1010.             else if (CountDataPoints == 1)
  1011.             {
  1012.                 Median = DataPoints[0];
  1013.             }
  1014.             for (int Row=0;Row<Rows;Row++)
  1015.             {
  1016.                 if (GeneMask[Row][Column])
  1017.                 {
  1018.                     GeneData[Row][Column] -= Median;
  1019.                 }
  1020.             }
  1021.         }
  1022.         if (NormalizeArraysCheckBox->Checked)
  1023.         {
  1024.             float DataSum2 = 0;
  1025.             for (int Row=0;Row<Rows;Row++)
  1026.             {
  1027.                 if (GeneMask[Row][Column])
  1028.                 {
  1029.                     DataSum2 += pow(GeneData[Row][Column],2);
  1030.                 }
  1031.             }
  1032.             float DataMag = sqrt(DataSum2);
  1033.             if (DataMag > 0)
  1034.             {
  1035.                 for (int Row=0;Row<Rows;Row++)
  1036.                 {
  1037.                     if (GeneMask[Row][Column])
  1038.                     {
  1039.                         GeneData[Row][Column] /= DataMag;
  1040.                     }
  1041.                 }
  1042.             }
  1043.         }
  1044.         free_vector(DataPoints,1,Rows);
  1045.      }
  1046.      StatusBar1->SimpleText = "Done Adjusting Data";
  1047. }
  1048. /* Distance Functions for Clustering */
  1049. /* Old Function that returns only Pearson Correlation */
  1050. unsigned short TMainForm::Distance(double **Data, bool **Mask, double *Weight,
  1051.     bool Centered, bool Absolute, int elem1, int elem2, int DataColumns)
  1052. {
  1053.     return Correlation(Data,Mask,Weight,Centered,Absolute,elem1,elem2,DataColumns);
  1054. }
  1055. unsigned short TMainForm::Distance(int Metric, double **Data, bool **Mask, double *Weight,
  1056.     int elem1, int elem2, int DataColumns)
  1057. {
  1058.     int i;
  1059.     int k;
  1060.     float *Vector1;
  1061.     float *Vector2;
  1062.     float d,zd,probd,rs,probrs;
  1063.     float tau, tauz, taup;
  1064.     switch (Metric)
  1065.     {
  1066.         /* Uncentered correlation */
  1067.         case 0:
  1068.         default:
  1069.             return Correlation(Data,Mask,Weight,false,false,elem1,elem2,DataColumns);
  1070.             break;
  1071.         case 2:
  1072.             return Correlation(Data,Mask,Weight,false,true,elem1,elem2,DataColumns);
  1073.             break;
  1074.         /* Centered correlation */
  1075.         case 1:
  1076.             return Correlation(Data,Mask,Weight,true,false,elem1,elem2,DataColumns);
  1077.             break;
  1078.         case 3:
  1079.             return Correlation(Data,Mask,Weight,true,true,elem1,elem2,DataColumns);
  1080.             break;
  1081.         /* Euclidean distance */
  1082.         //case 4:
  1083.         /* Spearman Rank */
  1084.         case 4:
  1085.             rs = 0;
  1086. #ifdef NUMREC
  1087.             Vector1 = vector(1,DataColumns);
  1088.             Vector2 = vector(1,DataColumns);
  1089.             k=0;
  1090.             for (i=0; i<DataColumns; i++)
  1091.             {
  1092.                 if ( (Mask[elem1][i] == true) && (Mask[elem2][i] == true) )
  1093.                 {
  1094.                     k++;
  1095.                     Vector1[k] = Data[elem1][i];
  1096.                     Vector2[k] = Data[elem2][i];
  1097.                 }
  1098.             }
  1099.             if (k > 1)
  1100.             {
  1101.                 spear(Vector1,Vector2,k,&d,&zd,&probd,&rs,&probrs);
  1102.             }
  1103.             else
  1104.             {
  1105.                 rs = 0;
  1106.             }
  1107.             free_vector(Vector1,1,DataColumns);
  1108.             free_vector(Vector2,1,DataColumns);
  1109. #endif
  1110.             return (unsigned short) (16384.0 * (1.0 - rs));
  1111.             break;
  1112.         /* Kendall's Tau */
  1113.         case 5:
  1114.             k = 0;
  1115.             tau = 0;
  1116. #ifdef NUMREC
  1117.             Vector1 = vector(1,DataColumns);
  1118.             Vector2 = vector(1,DataColumns);
  1119.             for (i=0; i<DataColumns; i++)
  1120.             {
  1121.                 if ( (Mask[elem1][i] == true) && (Mask[elem2][i] == true) )
  1122.                 {
  1123.                     k++;
  1124.                     Vector1[k] = Data[elem1][i];
  1125.                     Vector2[k] = Data[elem2][i];
  1126.                 }
  1127.             }
  1128.             if (k > 1)
  1129.             {
  1130.                 kendl1(Vector1, Vector2, k, &tau, &tauz, &taup);
  1131.             }
  1132.             else
  1133.             {
  1134.                 tau = 0;
  1135.             }
  1136.             free_vector(Vector1,1,DataColumns);
  1137.             free_vector(Vector2,1,DataColumns);
  1138. #endif
  1139.             return (unsigned short) (16384.0 * (1.0 - tau));
  1140.             break;
  1141.     }
  1142. }
  1143. /* Pearson Correlation */
  1144. unsigned short TMainForm::Correlation(double **Data, bool **Mask, double *Weight,
  1145.                 bool Centered, bool Absolute, int elem1, int elem2, int DataColumns)
  1146. {
  1147.     int i;
  1148.     double Sum1, Sum2;
  1149.     double Sum11, Sum22;
  1150.     double Sum12;
  1151.     double Ave1, Ave2;
  1152.     double Norm;
  1153.     double Corr = -1.0;
  1154.     double Count = 0;
  1155.     Sum1 = 0;
  1156.     Sum2 = 0;
  1157.     Sum11 = 0;
  1158.     Sum22 = 0;
  1159.     Sum12 = 0;
  1160.     for (i=0;i<DataColumns;i++)
  1161.     {
  1162.         try
  1163.         {
  1164.         if ( (Mask[elem1][i] == true) && (Mask[elem2][i] == true) )
  1165.         {
  1166.             Sum1  += Weight[i]*Data[elem1][i];
  1167.             Sum2  += Weight[i]*Data[elem2][i];
  1168.             Sum11 += Weight[i]*Data[elem1][i] * Data[elem1][i];
  1169.             Sum22 += Weight[i]*Data[elem2][i] * Data[elem2][i];
  1170.             Sum12 += Weight[i]*Data[elem1][i] * Data[elem2][i];
  1171.             Count += Weight[i];
  1172.         }
  1173.         }
  1174.         catch (Exception &E)
  1175.         {
  1176.             Sum1 = 0;
  1177.         }
  1178.     }
  1179.     if (Count > 0)
  1180.     {
  1181.         if (Centered)
  1182.         {
  1183.             Ave1 = Sum1/Count;
  1184.             Ave2 = Sum2/Count;
  1185.         }
  1186.         else
  1187.         {
  1188.             Ave1 = 0;
  1189.             Ave2 = 0;
  1190.         }
  1191.         try
  1192.         {
  1193.             Norm = sqrt(
  1194.                  max(0.0,Sum11 - Count * Ave1 * Ave1)
  1195.                  *
  1196.                  max(0.0,Sum22 - Count * Ave2 * Ave2)
  1197.                  );
  1198.         }
  1199.         catch (Exception &E)
  1200.         {
  1201.         }
  1202.         if ( (Norm > 0) )
  1203.         {
  1204.             Corr = (Sum12 - Count * Ave1 * Ave2)
  1205.                     / (Norm);
  1206.         }
  1207.         if (Absolute == true)
  1208.         {
  1209.             return (unsigned short) (32768.0 * (1.0 - fabs(Corr)));
  1210.         }
  1211.         else
  1212.         {
  1213.             return (unsigned short) (16384.0 * (1.0 - Corr));
  1214.         }
  1215.     }
  1216.     else
  1217.     {
  1218.         return 0;
  1219.     }
  1220. }
  1221. /* Pearson Correlation without Centered and Absolute options */
  1222. float TMainForm::Correlation(double **Data, bool **Mask, double *Weight,
  1223.                 int elem1, int elem2, int DataColumns)
  1224. {
  1225.     int i;
  1226.     bool Centered = false;
  1227.     //bool Absolute = false;
  1228.     double Sum1, Sum2;
  1229.     double Sum11, Sum22;
  1230.     double Sum12;
  1231.     double Ave1, Ave2;
  1232.     double Norm1, Norm2;
  1233.     float Corr = -1.0;
  1234.     double Count = 0;
  1235.     Sum1 = 0;
  1236.     Sum2 = 0;
  1237.     Sum11 = 0;
  1238.     Sum22 = 0;
  1239.     Sum12 = 0;
  1240.     for (i=0;i<DataColumns;i++)
  1241.     {
  1242.         try
  1243.         {
  1244.         if ( (Mask[elem1][i] == true) && (Mask[elem2][i] == true) )
  1245.         {
  1246.             Sum1  += Weight[i]*Data[elem1][i];
  1247.             Sum2  += Weight[i]*Data[elem2][i];
  1248.             Sum11 += Weight[i]*Data[elem1][i] * Data[elem1][i];
  1249.             Sum22 += Weight[i]*Data[elem2][i] * Data[elem2][i];
  1250.             Sum12 += Weight[i]*Data[elem1][i] * Data[elem2][i];
  1251.             Count += Weight[i];
  1252.         }
  1253.         }
  1254.         catch (Exception &E)
  1255.         {
  1256.             Sum1 = 0;
  1257.         }
  1258.     }
  1259.     if (Count > 0)
  1260.     {
  1261.         if (Centered)
  1262.         {
  1263.             Ave1 = Sum1/Count;
  1264.             Ave2 = Sum2/Count;
  1265.         }
  1266.         else
  1267.         {
  1268.             Ave1 = 0;
  1269.             Ave2 = 0;
  1270.         }
  1271.         try
  1272.         {
  1273.             Norm1 = sqrt(max(0.0,Sum11 - 2 * Ave1 * Sum1 + Count * Ave1 * Ave1));
  1274.             Norm2 = sqrt(max(0.0,Sum22 - 2 * Ave2 * Sum2 + Count * Ave2 * Ave2));
  1275.         }
  1276.         catch (Exception &E)
  1277.         {
  1278.         }
  1279.         if ( (Norm1 > 0) && (Norm2 > 0) )
  1280.         {
  1281.             Corr = (Sum12 - Sum1 * Ave2 - Sum2 * Ave1 + Count * Ave1 * Ave2)
  1282.                     / (Norm1 * Norm2);
  1283.         }
  1284.         return Corr;
  1285.     }
  1286.     else
  1287.     {
  1288.         return 0;
  1289.     }
  1290. }
  1291. /* Button Pressed for Average Linkage Hierarchical Clustering: Setup and Execute */
  1292. void __fastcall TMainForm::AverageLinkageClusterButtonClick(TObject *Sender)
  1293. {
  1294.     int i,j;
  1295.     StatusBar1->SimpleText = "Initializing";
  1296.     // Get ClusterID for file names from user input
  1297.     JobName = AnsiString(ClusterName);
  1298.     if (JobNameEdit->Text.Length() > 0)
  1299.     {
  1300.         JobName = JobNameEdit->Text;
  1301.     }
  1302.     bool ClusterGenes = ClusterGenesCheckBox->Checked;
  1303.     bool ClusterArrays = ClusterArraysCheckBox->Checked;
  1304.     bool CalculateGeneWeights = CalculateGeneWeightsCheckBox->Checked;
  1305.     bool CalculateArrayWeights = CalculateArrayWeightsCheckBox->Checked;
  1306.     int *ColumnOrder = new int[Columns];
  1307.     AnsiString *ArrayID = new AnsiString[2*Columns-1];
  1308.     for (i=0;i<Columns;i++)
  1309.     {
  1310.         ColumnOrder[i] = i;
  1311.         ArrayID[i] = "ARRY" + AnsiString(i) + "X";
  1312.     }
  1313.     if (CalculateGeneWeights == true)
  1314.     {
  1315.         // Generate array data structures
  1316.         // This is a wasteful way of doing it, but makes
  1317.         // the coding easier for me
  1318.         double **ArrayData = new double*[2*Columns-1];
  1319.         bool   **ArrayMask = new bool*[2*Columns-1];
  1320.         for (i=0;i<2*Columns-1;i++)
  1321.         {
  1322.             ArrayData[i] = new double[Rows];
  1323.             ArrayMask[i] = new bool[Rows];
  1324.             if (i<Columns)
  1325.             {
  1326.                for (j=0;j<Rows;j++)
  1327.                {
  1328.                    ArrayData[i][j] = GeneData[j][i];
  1329.                    ArrayMask[i][j] = GeneMask[j][i];
  1330.                }
  1331.             }
  1332.         }
  1333.         TStringList *ArrayTreeFile = new TStringList();
  1334.         TStringList *ArrayClusterOrder = new TStringList();
  1335.         Cluster(ArrayData,ArrayMask,Columns,Rows,
  1336.             ArrayTreeFile,ArrayOrder,ArrayWeight,GeneWeight,ArrayID,
  1337.             ArrayMetricComboBox->ItemIndex,
  1338.             true,ArrayWeightCutoff,ArrayWeightExp,
  1339.             ArrayClusterOrder,StatusBar1,false,NULL);
  1340.         delete ArrayClusterOrder;
  1341.         for (i=0;i<2*Columns-1;i++)
  1342.         {
  1343.             delete ArrayData[i];
  1344.             delete ArrayMask[i];
  1345.         }
  1346.         delete ArrayData;
  1347.         delete ArrayMask;
  1348.     }
  1349.     int *RowOrder = new int[Rows];
  1350.     AnsiString *GeneID = new AnsiString[2*Rows-1];
  1351.     for (i=0;i<Rows;i++)
  1352.     {
  1353.         RowOrder[i] = i;
  1354.         GeneID[i] = AnsiString("GENE") + AnsiString(i) + AnsiString("X");
  1355.     }
  1356.     if (ClusterGenes == true)
  1357.     {
  1358.         TStringList *GeneTreeFile = new TStringList();
  1359.         TStringList *GeneClusterOrder = new TStringList();
  1360.         if (CalculateArrayWeights == true)
  1361.         {
  1362.             Cluster(GeneData,GeneMask,Rows,Columns,
  1363.                 GeneTreeFile,GeneOrder,GeneWeight, ArrayWeight,GeneID,
  1364.                 GeneMetricComboBox->ItemIndex,
  1365.                 true,GeneWeightCutoff,GeneWeightExp,
  1366.                 GeneClusterOrder,StatusBar1,false,NULL);
  1367.         }
  1368.         else
  1369.         {
  1370.             double *NullGeneWeight = new double[Rows];
  1371.             Cluster(GeneData,GeneMask,Rows,Columns,
  1372.                 GeneTreeFile,GeneOrder,NullGeneWeight,ArrayWeight,GeneID,
  1373.                 GeneMetricComboBox->ItemIndex,
  1374.                 false,1.0,1.0,
  1375.                 GeneClusterOrder,StatusBar1,false,NULL);
  1376.             delete NullGeneWeight;
  1377.         }
  1378.         for (i=0;i<GeneClusterOrder->Count;i++)
  1379.         {
  1380.             RowOrder[i] = GeneClusterOrder->Strings[i].ToInt();
  1381.         }
  1382.         AnsiString TreeFileName = JobName + ".gtr";
  1383.         GeneTreeFile->SaveToFile(TreeFileName);
  1384.     }
  1385.     if (ClusterArrays == true)
  1386.     {
  1387.         // Generate array data structures
  1388.         // This is a wasteful way of doing it, but makes
  1389.         // the coding easier for me
  1390.         double **ArrayData = new double*[2*Columns-1];
  1391.         bool   **ArrayMask = new bool*[2*Columns-1];
  1392.         for (i=0;i<2*Columns-1;i++)
  1393.         {
  1394.             ArrayData[i] = new double[Rows];
  1395.             ArrayMask[i] = new bool[Rows];
  1396.             if (i<Columns)
  1397.             {
  1398.             for (j=0;j<Rows;j++)
  1399.             {
  1400.                 ArrayData[i][j] = GeneData[j][i];
  1401.                 ArrayMask[i][j] = GeneMask[j][i];
  1402.             }
  1403.             }
  1404.         }
  1405.         TStringList *ArrayTreeFile = new TStringList();
  1406.         TStringList *ArrayClusterOrder = new TStringList();
  1407.         Cluster(ArrayData,ArrayMask,Columns,Rows,
  1408.             ArrayTreeFile,ArrayOrder,ArrayWeight,GeneWeight,ArrayID,
  1409.             ArrayMetricComboBox->ItemIndex,
  1410.             false,1.0,1.0,ArrayClusterOrder,StatusBar1,false,NULL);
  1411.         for (i=0;i<ArrayClusterOrder->Count;i++)
  1412.         {
  1413.             ColumnOrder[i] = ArrayClusterOrder->Strings[i].ToInt();
  1414.         }
  1415.         delete ArrayClusterOrder;
  1416.         for (i=0;i<2*Columns-1;i++)
  1417.         {
  1418.             delete ArrayData[i];
  1419.             delete ArrayMask[i];
  1420.         }
  1421.         delete ArrayData;
  1422.         delete ArrayMask;
  1423.         AnsiString ArrayTreeFileName = JobName + ".atr";
  1424.         ArrayTreeFile->SaveToFile(ArrayTreeFileName);
  1425.         delete ArrayTreeFile;
  1426.     }
  1427.     AnsiString OutString;
  1428.     TStringList *DataFile = new TStringList();
  1429.     // Now make output .cdt file
  1430.     OutString = "";
  1431.     if (ClusterGenes == true)
  1432.     {
  1433.         OutString += AnsiString("GID") + AnsiString("t");
  1434.     }
  1435.     OutString += Headers->Strings[0] + AnsiString("t");
  1436.     OutString += AnsiString("NAME") + AnsiString("t");
  1437.     OutString += "GWEIGHT";
  1438.     // Now add headers for data columns
  1439.     for (i=0;i<Columns;i++)
  1440.     {
  1441.         OutString += "t";
  1442.         OutString += AnsiString(Headers->Strings[InColumn[ColumnOrder[i]]]);
  1443.     }
  1444.     DataFile->Add(OutString);
  1445.     if (ClusterArrays == true)
  1446.     {
  1447.         OutString = AnsiString("AID");
  1448.         if (ClusterGenes == true)
  1449.         {
  1450.             OutString += AnsiString("t");
  1451.         }
  1452.         OutString += AnsiString("t");
  1453.         OutString += AnsiString("t");
  1454.         for (i=0;i<Columns;i++)
  1455.         {
  1456.             OutString += "t";
  1457.             OutString += ArrayID[ColumnOrder[i]];
  1458.         }
  1459.         DataFile->Add(OutString);
  1460.     }
  1461.     {
  1462.         OutString = AnsiString("EWEIGHT");
  1463.         if (ClusterGenes == true)
  1464.         {
  1465.             OutString += AnsiString("t");
  1466.         }
  1467.         OutString += AnsiString("t");
  1468.         OutString += AnsiString("t");
  1469.         for (i=0;i<Columns;i++)
  1470.         {
  1471.             OutString += "t";
  1472.             OutString += ArrayWeight[ColumnOrder[i]];
  1473.         }
  1474.     }
  1475.     DataFile->Add(OutString);
  1476.     int index;
  1477.     TFloatFormat Format = ffGeneral;
  1478.     for (i=0;i<Rows;i++)
  1479.     {
  1480.         index = RowOrder[i];
  1481.         OutString = "";
  1482.         if (ClusterGenes == true)
  1483.         {
  1484.             OutString += GeneID[index] + "t";
  1485.         }
  1486.         OutString += AnsiString(UniqID[index]) + "t" + AnsiString(GeneName[index]);
  1487.         OutString += "t" + AnsiString(GeneWeight[index]);
  1488.         for (j=0;j<Columns;j++)
  1489.         {
  1490.             if (GeneMask[index][ColumnOrder[j]] == true)
  1491.             {
  1492.                 OutString += "t" + AnsiString(FloatToStrF(GeneData[index][ColumnOrder[j]],Format,4,2));
  1493.             }
  1494.             else
  1495.             {
  1496.                 OutString += "t";
  1497.             }
  1498.         }
  1499.         DataFile->Add(OutString);
  1500.     }
  1501.     AnsiString DataFileName = JobName + ".cdt";
  1502.     DataFile->SaveToFile(DataFileName);
  1503.     for (i=0;i<2*Columns-1;i++)
  1504.     {
  1505.         ArrayID[i] = "";
  1506.     }
  1507.     for (i=0;i<2*Rows-1;i++)
  1508.     {
  1509.         GeneID[i] = "";
  1510.     }
  1511.     delete ArrayID;
  1512.     delete GeneID;
  1513.     delete ColumnOrder;
  1514.     delete RowOrder;
  1515.     StatusBar1->SimpleText = "Done Clustering";
  1516. }
  1517. //---------------------------------------------------------------------------
  1518. /* Average Linkage Hierarchical Clustering Code */
  1519. void    TMainForm::Cluster(double **ClusterData, bool **ClusterMask,
  1520.         int ClusterRows, int ClusterColumns,
  1521.         TStringList *TreeFile, double *Order, double *RowWeight, double *ColumnWeight,
  1522.         AnsiString *ID, int DistFunction,
  1523.         bool CalculateWeights, double WeightCutoff, double WeightPower,
  1524.         TStringList *ClusterOrder, TStatusBar *StatusBar,
  1525.         bool ReturnTNode, TNode *TopNode)
  1526. {
  1527.         int i,j,k,l,m;
  1528.         unsigned short *minval;
  1529.         int *minpair;
  1530.         int *elements;
  1531.         AnsiString OutString;
  1532.         unsigned short **Dist;
  1533.         int **NodeElement;
  1534.         double *NodeDistance;
  1535.         double *CalcWeight;
  1536.         int element1, element2;
  1537.         Dist = new unsigned short*[2*ClusterRows-1];
  1538.         minval = new unsigned short[2*ClusterRows-1];
  1539.         minpair = new int[2*ClusterRows-1];
  1540.         elements = new int[2*ClusterRows-1];
  1541.         NodeElement = new int*[2*ClusterRows-1];
  1542.         NodeDistance = new double[2*ClusterRows-1];
  1543.         CalcWeight = new double[2*ClusterRows-1];
  1544.         bool SaveDistances = false;
  1545.         double WeightDist;
  1546.         for (i=0;i<ClusterRows;i++)
  1547.         {
  1548.             Dist[i] = new unsigned short[2*ClusterRows-1];
  1549.         }
  1550.         for (i=0;i<2*ClusterRows-1;i++)
  1551.         {
  1552.             minval[i] = 32769;
  1553.             elements[i] = 1;
  1554.             NodeElement[i] = new int[2];
  1555.             CalcWeight[i] = 1;
  1556.             NodeDistance[i] = 0.0;
  1557.         }
  1558.         bool Centered = false;
  1559.         if ((DistFunction == 1) || (DistFunction == 3) )
  1560.         {
  1561.             Centered = true;
  1562.         }
  1563.         bool Absolute = false;
  1564.         if ((DistFunction == 3) || (DistFunction == 4) )
  1565.         {
  1566.             Absolute = true;
  1567.         }
  1568.         bool CalcInferredDistances = false;
  1569.         TStringList **MemberList;
  1570.         unsigned short **TreeDist;
  1571.         if (CalcInferredDistances == true)
  1572.         {
  1573.             MemberList = new TStringList*[2*ClusterRows-1];
  1574.             TreeDist = new unsigned short*[ClusterRows];
  1575.             for (i=0;i<2*ClusterRows-1;i++)
  1576.             {
  1577.                 MemberList[i] = new TStringList();
  1578.                 if (i<ClusterRows)
  1579.                 {
  1580.                     MemberList[i]->Add(AnsiString(i));
  1581.                     TreeDist[i] = new unsigned short[ClusterRows];
  1582.                 }
  1583.             }
  1584.         }
  1585.         int TotalDistance = ClusterRows * (ClusterRows - 1) / 2;
  1586.         /* First step is to compute the distance matrix
  1587.         This is the slowest step */
  1588.         for (i=0;i<ClusterRows;i++)
  1589.         {
  1590.             Dist[i][i] = 0.0;
  1591.             for (j=0;j<i;j++)
  1592.             {
  1593.                 Dist[i][j] = Distance(DistFunction,ClusterData,ClusterMask,ColumnWeight,
  1594.                     i,j,ClusterColumns);
  1595.                 Dist[j][i] = Dist[i][j];
  1596.                 if (CalculateWeights == true)
  1597.                 {
  1598.                     WeightDist = ( (double) (32768 - Dist[i][j])) /32768.0;
  1599.                     WeightDist = max(0.0, (WeightDist - WeightCutoff)/(1.0 - WeightCutoff));
  1600.                     WeightDist = pow(WeightDist,WeightPower);
  1601.                     CalcWeight[i] += WeightDist;
  1602.                     CalcWeight[j] += WeightDist;
  1603.                 }
  1604.                 if (Dist[i][j] < minval[i])
  1605.                 {
  1606.                     minval[i] = Dist[i][j];
  1607.                     minpair[i] = j;
  1608.                 }
  1609.                 if (Dist[i][j] < minval[j])
  1610.                 {
  1611.                     minval[j] = Dist[i][j];
  1612.                     minpair[j] = i;
  1613.                 }
  1614.             }
  1615.             StatusBar->SimpleText = "Calculating Distances " + AnsiString(i*(i+1)/2) + " of "
  1616.                 + AnsiString(TotalDistance);
  1617.             Application->ProcessMessages();
  1618.         }
  1619.         TStringList *MinList = new TStringList();
  1620.         for (i=0;i<ClusterRows;i++)
  1621.         {
  1622.             MinList->Add(AnsiString(minval[i]));
  1623.         }
  1624.         MinList->SaveToFile("minlist.txt");
  1625.         delete MinList;
  1626.         bool *Active;
  1627.         Active = new bool[2*ClusterRows-1];
  1628.         for (i=0;i<ClusterRows;i++)
  1629.         {
  1630.             Active[i] = true;
  1631.         }
  1632.         for (i=ClusterRows;i<2*ClusterRows-1;i++)
  1633.         {
  1634.             Active[i] = false;
  1635.         }
  1636.         unsigned short minminval;
  1637.         int min1, min2;
  1638.         int nodeindex;
  1639.         //int node;
  1640.         /* Now we join nodes */
  1641.         /* If we are going to return TNode, need to set up TNodes */
  1642.         TNode **Nodes;
  1643.         if (ReturnTNode)
  1644.         {
  1645.            Nodes = new TNode*[2*ClusterRows-1];
  1646.            for (i=0;i<2*ClusterRows-1;i++)
  1647.            {
  1648.                Nodes[i] = new TNode();
  1649.                if (i < ClusterRows)
  1650.                {
  1651.                    Nodes[i]->IsNode = false;
  1652.                    Nodes[i]->ID = AnsiString(i);
  1653.                }
  1654.                else
  1655.                {
  1656.                    Nodes[i]->IsNode = true;
  1657.                }
  1658.            }
  1659.         }
  1660.         for (nodeindex=ClusterRows; nodeindex<2*ClusterRows-1;nodeindex++)
  1661.         {
  1662.             ID[nodeindex] = "NODE" + AnsiString(nodeindex-ClusterRows+1) + "X";
  1663.             minminval = 32769;
  1664.             for (i=0;i<2*ClusterRows-1;i++)
  1665.             {
  1666.                 if (Active[i] == true)
  1667.                 {
  1668.                     if (minval[i] < minminval)
  1669.                     {
  1670.                         minminval = minval[i];
  1671.                         min1 = i;
  1672.                         min2 = minpair[i];
  1673.                     }
  1674.                 }
  1675.             }
  1676.             /* When we get here min1 and min2 are the elements that are to be joined */
  1677.         Active[min1] = false;
  1678.         Active[min2] = false;
  1679.         if (Order[min1] > Order[min2])
  1680.         {
  1681.             NodeElement[nodeindex][0] = min1;
  1682.             NodeElement[nodeindex][1] = min2;
  1683.         }
  1684.         else
  1685.         {
  1686.             NodeElement[nodeindex][1] = min1;
  1687.             NodeElement[nodeindex][0] = min2;
  1688.         }
  1689.         NodeDistance[nodeindex] = ((double) minminval)/16384.0;
  1690.         NodeDistance[nodeindex] = max(NodeDistance[nodeindex],NodeDistance[min1]);
  1691.         NodeDistance[nodeindex] = max(NodeDistance[nodeindex],NodeDistance[min2]);
  1692.         if (ReturnTNode)
  1693.         {
  1694.                Nodes[nodeindex]->Child1 = Nodes[NodeElement[nodeindex][0]];
  1695.                Nodes[nodeindex]->Child2 = Nodes[NodeElement[nodeindex][1]];
  1696.                Nodes[nodeindex]->Length = 1.0 - NodeDistance[nodeindex];
  1697.         }
  1698.         if (CalcInferredDistances == true)
  1699.         {
  1700.             int elem1,elem2,ielem1,ielem2;
  1701.             for (elem1=0;elem1<MemberList[min1]->Count;elem1++)
  1702.             {
  1703.                 for (elem2=0;elem2<MemberList[min2]->Count;elem2++)
  1704.                 {
  1705.                     ielem1 = (MemberList[min1]->Strings[elem1]).ToInt();
  1706.                     ielem2 = (MemberList[min2]->Strings[elem2]).ToInt();
  1707.                     TreeDist[ielem1][ielem2] = (NodeDistance[nodeindex] * 16384);
  1708.                     TreeDist[ielem2][ielem1] = (NodeDistance[nodeindex] * 16384);
  1709.                 }
  1710.             }
  1711.             MemberList[nodeindex]->AddStrings(MemberList[min1]);
  1712.             MemberList[nodeindex]->AddStrings(MemberList[min2]);
  1713.             delete MemberList[min1];
  1714.             delete MemberList[min2];
  1715.         }
  1716.         OutString = ID[nodeindex] + AnsiString("t") + ID[NodeElement[nodeindex][0]]
  1717.                 + AnsiString("t") + ID[NodeElement[nodeindex][1]] + AnsiString("t")
  1718.                 + AnsiString(1.0 - NodeDistance[nodeindex]);
  1719.         TreeFile->Add(OutString);
  1720.         StatusBar->SimpleText = "Generating Node " + AnsiString(nodeindex-ClusterRows+1) + " of " + AnsiString(ClusterRows-1);
  1721.         Application->ProcessMessages();
  1722.         elements[nodeindex] = elements[min1] + elements[min2];
  1723.         for (k=0;k<ClusterColumns;k++)
  1724.         {
  1725.             if ( (ClusterMask[min1][k] == true) && (ClusterMask[min2][k] == true) )
  1726.             {
  1727.                 ClusterData[nodeindex][k] =
  1728.                     (elements[min1] * ClusterData[min1][k] +
  1729.                         elements[min2] * ClusterData[min2][k]) /
  1730.                     (elements[min1] + elements[min2]);
  1731.                 ClusterMask[nodeindex][k] = true;
  1732.             }
  1733.             else if (ClusterMask[min1][k] == true)
  1734.             {
  1735.                 ClusterData[nodeindex][k] = ClusterData[min1][k];
  1736.                 ClusterMask[nodeindex][k] = true;
  1737.             }
  1738.             else if (ClusterMask[min2][k] == true)
  1739.             {
  1740.                 ClusterData[nodeindex][k] = ClusterData[min2][k];
  1741.                 ClusterMask[nodeindex][k] = true;
  1742.             }
  1743.             else
  1744.             {
  1745.                 ClusterMask[nodeindex][k] = false;
  1746.             }
  1747.         }
  1748.         Order[nodeindex] = (elements[min1]*Order[min1] + elements[min2]*Order[min2])/(elements[min1] + elements[min2]);
  1749.         Dist[nodeindex] = new unsigned short[2*ClusterRows-1];
  1750.         if (SaveDistances == false)
  1751.         {
  1752.             delete Dist[min1];
  1753.             delete Dist[min2];
  1754.         }
  1755.         for (l=0;l<2*ClusterRows-1;l++)
  1756.         {
  1757.             if (Active[l] == true)
  1758.             {
  1759.                 Dist[nodeindex][l] =
  1760.                     Distance(DistFunction,ClusterData,ClusterMask,ColumnWeight,
  1761.                     nodeindex,l,ClusterColumns);
  1762.                 Dist[l][nodeindex] = Dist[nodeindex][l];
  1763.                 if (Dist[nodeindex][l] < minval[nodeindex])
  1764.                 {
  1765.                     minval[nodeindex] = Dist[nodeindex][l];
  1766.                     minpair[nodeindex] = l;
  1767.                 }
  1768.                 //Rescan for min if minpair was one of the fused elements
  1769.                 if ( (minpair[l] == min1) || (minpair[l] == min2) )
  1770.                 {
  1771.                     minval[l] = 32769;
  1772.                     for (m=0;m<2*ClusterRows-1;m++)
  1773.                     {
  1774.                         if ( (Active[m] == true) && (l != m) )
  1775.                         {
  1776.                             if (Dist[l][m] < minval[l])
  1777.                             {
  1778.                                 minval[l] = Dist[l][m];
  1779.                                 minpair[l] = m;
  1780.                             }
  1781.                         }
  1782.                     }
  1783.                 }
  1784.                 //otherwise check new distance to see if it is new min
  1785.                 else if (Dist[nodeindex][l] < minval[l])
  1786.                 {
  1787.                     minval[l] = Dist[nodeindex][l];
  1788.                     minpair[l] = nodeindex;
  1789.                 }
  1790.             }
  1791.         }
  1792.         Active[nodeindex] = true;
  1793.         }
  1794.         if (SaveDistances == false)
  1795.         {
  1796.             delete Dist[2*ClusterRows-2];
  1797.         }
  1798.         TList *NewList = new TList();
  1799.         TList *OutList = new TList();
  1800.         int **Elements;
  1801.         Elements = new int*[2*ClusterRows-1];
  1802.         for (i=0;i<2*ClusterRows-1;i++)
  1803.         {
  1804.             Elements[i] = new int;
  1805.             *Elements[i] = i;
  1806.         }
  1807.         OutList->Clear();
  1808.         OutList->Add((void *)Elements[2*ClusterRows-2]);
  1809.         int Position;
  1810.         bool Replaced;
  1811.         Replaced = true;
  1812.         while (Replaced == true)
  1813.         {
  1814.             Replaced = false;
  1815.             for (Position = 0; Position < OutList->Count; Position ++)
  1816.             {
  1817.                 nodeindex =  *(int *) OutList->Items[Position];
  1818.                 if (nodeindex >= 0)
  1819.                 {
  1820.                     if (nodeindex < ClusterRows)
  1821.                     {
  1822.                         NewList->Add((void *) Elements[nodeindex]);
  1823.                     }
  1824.                     else
  1825.                     {
  1826.                         element1 =  NodeElement[nodeindex][0];
  1827.                         element2 =  NodeElement[nodeindex][1];
  1828.                         NewList->Add((void *) Elements[element1]);
  1829.                         NewList->Add((void *) Elements[element2]);
  1830.                         Replaced = true;
  1831.                     }
  1832.                 }
  1833.             }
  1834.             OutList->Clear();
  1835.             for (i=0;i<NewList->Count;i++)
  1836.             {
  1837.                 OutList->Add(NewList->Items[i]);
  1838.             }
  1839.             NewList->Clear();
  1840.         }
  1841.         int index;
  1842.         ClusterOrder->Clear();
  1843.         if (SaveDistances == true)
  1844.         {
  1845.             if (DistFileDialogBox->Execute())
  1846.             {
  1847.                 TFileStream *DistFile = new TFileStream(DistFileDialogBox->FileName,fmCreate);
  1848.                 int ii, ij;
  1849.                 for (i=0;i<OutList->Count;i++)
  1850.                 {
  1851.                     ii = *(int *)OutList->Items[i];
  1852.                     for (j=0;j<OutList->Count;j++)
  1853.                     {
  1854.                         {
  1855.                             ij = *(int *)OutList->Items[j];
  1856.                             DistFile->Write(&Dist[ii][ij],2);
  1857.                         }
  1858.                     }
  1859.                 }
  1860.                 delete DistFile;
  1861.                 for (i=0;i<2*ClusterRows-1;i++)
  1862.                 {
  1863.                     delete Dist[i];
  1864.                 }
  1865.             }
  1866.         }
  1867.         if (CalcInferredDistances == true)
  1868.         {
  1869.             if (DistFileDialogBox->Execute())
  1870.             {
  1871.                 TFileStream *DistFile = new TFileStream(DistFileDialogBox->FileName,fmCreate);
  1872.                 int ii, ij;
  1873.                 for (i=0;i<OutList->Count;i++)
  1874.                 {
  1875.                     ii = *(int *)OutList->Items[i];
  1876.                     for (j=0;j<OutList->Count;j++)
  1877.                     {
  1878.                         {
  1879.                             ij = *(int *)OutList->Items[j];
  1880.                             DistFile->Write(&TreeDist[ii][ij],2);
  1881.                         }
  1882.                     }
  1883.                 }
  1884.                 delete DistFile;
  1885.                 for (i=0;i<ClusterRows;i++)
  1886.                 {
  1887.                     delete TreeDist[i];
  1888.                 }
  1889.             }
  1890.             delete TreeDist;
  1891.         }
  1892.         for (i=0;i<OutList->Count;i++)
  1893.         {
  1894.             index = *(int *)OutList->Items[i];
  1895.             ClusterOrder->Add(index);
  1896.         }
  1897.         for (i=0;i<2*ClusterRows-1;i++)
  1898.         {
  1899.             delete NodeElement[i];
  1900.             delete Elements[i];
  1901.         }
  1902.         if (CalculateWeights == true)
  1903.         {
  1904.             for (i=0;i<ClusterRows;i++)
  1905.             {
  1906.                 RowWeight[i] = 1/CalcWeight[i];
  1907.             }
  1908.         }
  1909.         delete Dist;
  1910.         delete NodeElement;
  1911.         delete Elements;
  1912.         delete NodeDistance;
  1913.         delete elements;
  1914.         delete minval;
  1915.         delete minpair;
  1916.         delete NewList;
  1917.         delete OutList;
  1918.         delete Active;
  1919.         delete CalcWeight;
  1920. }
  1921. //---------------------------------------------------------------------------
  1922. void __fastcall TMainForm::CompleteLinkageClusterButtonClick(TObject *Sender)
  1923. {
  1924.     int i,j;
  1925.     StatusBar1->SimpleText = "Initializing";
  1926.     // Get ClusterID for file names from user input
  1927.     JobName = AnsiString(ClusterName);
  1928.     if (JobNameEdit->Text.Length() > 0)
  1929.     {
  1930.         JobName = JobNameEdit->Text;
  1931.     }
  1932.     bool ClusterGenes = ClusterGenesCheckBox->Checked;
  1933.     bool ClusterArrays = ClusterArraysCheckBox->Checked;
  1934.     bool CalculateGeneWeights = CalculateGeneWeightsCheckBox->Checked;
  1935.     bool CalculateArrayWeights = CalculateArrayWeightsCheckBox->Checked;
  1936.     int *ColumnOrder = new int[Columns];
  1937.     AnsiString *ArrayID = new AnsiString[2*Columns-1];
  1938.     for (i=0;i<Columns;i++)
  1939.     {
  1940.         ColumnOrder[i] = i;
  1941.         ArrayID[i] = "ARRY" + AnsiString(i) + "X";
  1942.     }
  1943.     if (CalculateGeneWeights == true)
  1944.     {
  1945.         // Generate array data structures
  1946.         // This is a wasteful way of doing it, but makes
  1947.         // the coding easier for me
  1948.         double **ArrayData = new double*[2*Columns-1];
  1949.         bool   **ArrayMask = new bool*[2*Columns-1];
  1950.         for (i=0;i<2*Columns-1;i++)
  1951.         {
  1952.             ArrayData[i] = new double[Rows];
  1953.             ArrayMask[i] = new bool[Rows];
  1954.             if (i<Columns)
  1955.             {
  1956.                for (j=0;j<Rows;j++)
  1957.                {
  1958.                    ArrayData[i][j] = GeneData[j][i];
  1959.                    ArrayMask[i][j] = GeneMask[j][i];
  1960.                }
  1961.             }
  1962.         }
  1963.         TStringList *ArrayTreeFile = new TStringList();
  1964.         TStringList *ArrayClusterOrder = new TStringList();
  1965.         CompactCluster(ArrayData,ArrayMask,Columns,Rows,
  1966.             ArrayTreeFile,ArrayOrder,ArrayWeight,GeneWeight,ArrayID,
  1967.             ArrayMetricComboBox->ItemIndex,
  1968.             true,ArrayWeightCutoff,ArrayWeightExp,
  1969.             ArrayClusterOrder,StatusBar1,false,NULL);
  1970.         delete ArrayClusterOrder;
  1971.         for (i=0;i<2*Columns-1;i++)
  1972.         {
  1973.             delete ArrayData[i];
  1974.             delete ArrayMask[i];
  1975.         }
  1976.         delete ArrayData;
  1977.         delete ArrayMask;
  1978.     }
  1979.     int *RowOrder = new int[Rows];
  1980.     AnsiString *GeneID = new AnsiString[2*Rows-1];
  1981.     for (i=0;i<Rows;i++)
  1982.     {
  1983.         RowOrder[i] = i;
  1984.         GeneID[i] = AnsiString("GENE") + AnsiString(i) + AnsiString("X");
  1985.     }
  1986.     if (ClusterGenes == true)
  1987.     {
  1988.         TStringList *GeneTreeFile = new TStringList();
  1989.         TStringList *GeneClusterOrder = new TStringList();
  1990.         if (CalculateArrayWeights == true)
  1991.         {
  1992.             CompactCluster(GeneData,GeneMask,Rows,Columns,
  1993.                 GeneTreeFile,GeneOrder,GeneWeight, ArrayWeight,GeneID,
  1994.                 GeneMetricComboBox->ItemIndex,
  1995.                 true,GeneWeightCutoff,GeneWeightExp,
  1996.                 GeneClusterOrder,StatusBar1,false,NULL);
  1997.         }
  1998.         else
  1999.         {
  2000.             double *NullGeneWeight = new double[Rows];
  2001.             CompactCluster(GeneData,GeneMask,Rows,Columns,
  2002.                 GeneTreeFile,GeneOrder,NullGeneWeight,ArrayWeight,GeneID,
  2003.                 GeneMetricComboBox->ItemIndex,
  2004.                 false,1.0,1.0,
  2005.                 GeneClusterOrder,StatusBar1,false,NULL);
  2006.             delete NullGeneWeight;
  2007.         }
  2008.         for (i=0;i<GeneClusterOrder->Count;i++)
  2009.         {
  2010.             RowOrder[i] = GeneClusterOrder->Strings[i].ToInt();
  2011.         }
  2012.         AnsiString TreeFileName = JobName + ".gtr";
  2013.         GeneTreeFile->SaveToFile(TreeFileName);
  2014.     }
  2015.     if (ClusterArrays == true)
  2016.     {
  2017.         // Generate array data structures
  2018.         // This is a wasteful way of doing it, but makes
  2019.         // the coding easier for me
  2020.         double **ArrayData = new double*[2*Columns-1];
  2021.         bool   **ArrayMask = new bool*[2*Columns-1];
  2022.         for (i=0;i<2*Columns-1;i++)
  2023.         {
  2024.             ArrayData[i] = new double[Rows];
  2025.             ArrayMask[i] = new bool[Rows];
  2026.             if (i<Columns)
  2027.             {
  2028.             for (j=0;j<Rows;j++)
  2029.             {
  2030.                 ArrayData[i][j] = GeneData[j][i];
  2031.                 ArrayMask[i][j] = GeneMask[j][i];
  2032.             }
  2033.             }
  2034.         }
  2035.         TStringList *ArrayTreeFile = new TStringList();
  2036.         TStringList *ArrayClusterOrder = new TStringList();
  2037.         CompactCluster(ArrayData,ArrayMask,Columns,Rows,
  2038.             ArrayTreeFile,ArrayOrder,ArrayWeight,GeneWeight,ArrayID,
  2039.             ArrayMetricComboBox->ItemIndex,
  2040.             false,1.0,1.0,ArrayClusterOrder,StatusBar1,false,NULL);
  2041.         for (i=0;i<ArrayClusterOrder->Count;i++)
  2042.         {
  2043.             ColumnOrder[i] = ArrayClusterOrder->Strings[i].ToInt();
  2044.         }
  2045.         delete ArrayClusterOrder;
  2046.         for (i=0;i<2*Columns-1;i++)
  2047.         {
  2048.             delete ArrayData[i];
  2049.             delete ArrayMask[i];
  2050.         }
  2051.         delete ArrayData;
  2052.         delete ArrayMask;
  2053.         AnsiString ArrayTreeFileName = JobName + ".atr";
  2054.         ArrayTreeFile->SaveToFile(ArrayTreeFileName);
  2055.         delete ArrayTreeFile;
  2056.     }
  2057.     AnsiString OutString;
  2058.     TStringList *DataFile = new TStringList();
  2059.     // Now make output .cdt file
  2060.     OutString = "";
  2061.     if (ClusterGenes == true)
  2062.     {
  2063.         OutString += AnsiString("GID") + AnsiString("t");
  2064.     }
  2065.     OutString += Headers->Strings[0] + AnsiString("t");
  2066.     OutString += AnsiString("NAME") + AnsiString("t");
  2067.     OutString += "GWEIGHT";
  2068.     // Now add headers for data columns
  2069.     for (i=0;i<Columns;i++)
  2070.     {
  2071.         OutString += "t";
  2072.         OutString += AnsiString(Headers->Strings[InColumn[ColumnOrder[i]]]);
  2073.     }
  2074.     DataFile->Add(OutString);
  2075.     if (ClusterArrays == true)
  2076.     {
  2077.         OutString = AnsiString("AID");
  2078.         if (ClusterGenes == true)
  2079.         {
  2080.             OutString += AnsiString("t");
  2081.         }
  2082.         OutString += AnsiString("t");
  2083.         OutString += AnsiString("t");
  2084.         for (i=0;i<Columns;i++)
  2085.         {
  2086.             OutString += "t";
  2087.             OutString += ArrayID[ColumnOrder[i]];
  2088.         }
  2089.         DataFile->Add(OutString);
  2090.     }
  2091.     {
  2092.         OutString = AnsiString("EWEIGHT");
  2093.         if (ClusterGenes == true)
  2094.         {
  2095.             OutString += AnsiString("t");
  2096.         }
  2097.         OutString += AnsiString("t");
  2098.         OutString += AnsiString("t");
  2099.         for (i=0;i<Columns;i++)
  2100.         {
  2101.             OutString += "t";
  2102.             OutString += ArrayWeight[ColumnOrder[i]];
  2103.         }
  2104.     }
  2105.     DataFile->Add(OutString);
  2106.     int index;
  2107.     TFloatFormat Format = ffGeneral;
  2108.     for (i=0;i<Rows;i++)
  2109.     {
  2110.         index = RowOrder[i];
  2111.         OutString = "";
  2112.         if (ClusterGenes == true)
  2113.         {
  2114.             OutString += GeneID[index] + "t";
  2115.         }
  2116.         OutString += AnsiString(UniqID[index]) + "t" + AnsiString(GeneName[index]);
  2117.         OutString += "t" + AnsiString(GeneWeight[index]);
  2118.         for (j=0;j<Columns;j++)
  2119.         {
  2120.             if (GeneMask[index][ColumnOrder[j]] == true)
  2121.             {
  2122.                 OutString += "t" + AnsiString(FloatToStrF(GeneData[index][ColumnOrder[j]],Format,4,2));
  2123.             }
  2124.             else
  2125.             {
  2126.                 OutString += "t";
  2127.             }
  2128.         }
  2129.         DataFile->Add(OutString);
  2130.     }
  2131.     AnsiString DataFileName = JobName + ".cdt";
  2132.     DataFile->SaveToFile(DataFileName);
  2133.     for (i=0;i<2*Columns-1;i++)
  2134.     {
  2135.         ArrayID[i] = "";
  2136.     }
  2137.     for (i=0;i<2*Rows-1;i++)
  2138.     {
  2139.         GeneID[i] = "";
  2140.     }
  2141.     delete ArrayID;
  2142.     delete GeneID;
  2143.     delete ColumnOrder;
  2144.     delete RowOrder;
  2145.     StatusBar1->SimpleText = "Done Clustering";
  2146. }
  2147. //---------------------------------------------------------------------------
  2148. /* Compact/Complete Linkage Hierarchical Clustering Code */
  2149. void    TMainForm::CompactCluster(double **ClusterData, bool **ClusterMask,
  2150.         int ClusterRows, int ClusterColumns,
  2151.         TStringList *TreeFile, double *Order, double *RowWeight, double *ColumnWeight,
  2152.         AnsiString *ID, int DistFunction,
  2153.         bool CalculateWeights, double WeightCutoff, double WeightPower,
  2154.         TStringList *ClusterOrder, TStatusBar *StatusBar,
  2155.         bool ReturnTNode, TNode *TopNode)
  2156. {
  2157.         int i,j,k,l,m;
  2158.         ReturnTNode = true;
  2159.         unsigned short *minval;
  2160.         int *minpair;
  2161.         int *elements;
  2162.         AnsiString OutString;
  2163.         unsigned short **Dist;
  2164.         int **NodeElement;
  2165.         double *NodeDistance;
  2166.         double *CalcWeight;
  2167.         int element1, element2;
  2168.         
  2169.         TStringList *List1 = new TStringList();
  2170.         TStringList *List2 = new TStringList();
  2171.         Dist = new unsigned short*[2*ClusterRows-1];
  2172.         minval = new unsigned short[2*ClusterRows-1];
  2173.         minpair = new int[2*ClusterRows-1];
  2174.         elements = new int[2*ClusterRows-1];
  2175.         NodeElement = new int*[2*ClusterRows-1];
  2176.         NodeDistance = new double[2*ClusterRows-1];
  2177.         CalcWeight = new double[2*ClusterRows-1];
  2178.         int *iList1 = new int[ClusterRows];
  2179.         int *iList2 = new int[ClusterRows];
  2180.         bool SaveDistances = true;
  2181.         double WeightDist;
  2182.         for (i=0;i<ClusterRows;i++)
  2183.         {
  2184.             Dist[i] = new unsigned short[2*ClusterRows-1];
  2185.         }
  2186.         for (i=0;i<2*ClusterRows-1;i++)
  2187.         {
  2188.             minval[i] = 32769;
  2189.             elements[i] = 1;
  2190.             NodeElement[i] = new int[2];
  2191.             CalcWeight[i] = 1;
  2192.             NodeDistance[i] = 0.0;
  2193.         }
  2194.         bool Centered = false;
  2195.         if ((DistFunction == 1) || (DistFunction == 3) )
  2196.         {
  2197.             Centered = true;
  2198.         }
  2199.         bool Absolute = false;
  2200.         if ((DistFunction == 3) || (DistFunction == 4) )
  2201.         {
  2202.             Absolute = true;
  2203.         }
  2204.         bool CalcInferredDistances = false;
  2205.         TStringList **MemberList;
  2206.         unsigned short **TreeDist;
  2207.         if (CalcInferredDistances == true)
  2208.         {
  2209.             MemberList = new TStringList*[2*ClusterRows-1];
  2210.             TreeDist = new unsigned short*[ClusterRows];
  2211.             for (i=0;i<2*ClusterRows-1;i++)
  2212.             {
  2213.                 MemberList[i] = new TStringList();
  2214.                 if (i<ClusterRows)
  2215.                 {
  2216.                     MemberList[i]->Add(AnsiString(i));
  2217.                     TreeDist[i] = new unsigned short[ClusterRows];
  2218.                 }
  2219.             }
  2220.         }
  2221.         int TotalDistance = ClusterRows * (ClusterRows - 1) / 2;
  2222.         /* First step is to compute the distance matrix
  2223.         This is the slowest step */
  2224.         for (i=0;i<ClusterRows;i++)
  2225.         {
  2226.             Dist[i][i] = 0.0;
  2227.             for (j=0;j<i;j++)
  2228.             {
  2229.                 Dist[i][j] = Distance(DistFunction,ClusterData,ClusterMask,ColumnWeight,
  2230.                     i,j,ClusterColumns);
  2231.                 Dist[j][i] = Dist[i][j];
  2232.                 if (CalculateWeights == true)
  2233.                 {
  2234.                     WeightDist = ( (double) (32768 - Dist[i][j])) /32768.0;
  2235.                     WeightDist = max(0.0, (WeightDist - WeightCutoff)/(1.0 - WeightCutoff));
  2236.                     WeightDist = pow(WeightDist,WeightPower);
  2237.                     CalcWeight[i] += WeightDist;
  2238.                     CalcWeight[j] += WeightDist;
  2239.                 }