📄 tabledata.cpp
字号:
//---------------------------------------------------------------------------
#include <vcl.h>
#include <stdlib.h>
#include <math.h>
#pragma hdrstop
#include "TableData.h"
#include "MyUtils.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
AnsiString NextString(AnsiString* String)
{
AnsiString Field;
int delim = (*String).LastDelimiter("\t");
if (delim != 0)
{
Field = (*String).SubString(delim+1,(*String).Length()-delim);
(*String) = (*String).SubString(0,delim-1);
}
else
{
Field = (*String);
(*String) = (*String).SubString(0,0);
}
if ((Field.Length() == 0) && (delim == 0) )
{
return AnsiString("DONE");
}
else
{
return Field;
}
}
void __fastcall SplitString(AnsiString *String, TStringList *List)
{
AnsiString Field;
List->Clear();
while ((Field = NextString(String)) != "DONE")
{
List->Insert(0,Field);
}
}
AnsiString __fastcall RowDataInfoToString(float *OutRowData, int n, TTableObjectInfo *Info)
{
TFloatFormat Format = ffGeneral;
AnsiString Tmp = Info->ID + "\t" + Info->Name + "\t" + AnsiString(Info->Weight);
for (int i=0; i<n; i++)
{
Tmp += "\t";
if (OutRowData[i] != NODATA)
{
Tmp += AnsiString(FloatToStrF(OutRowData[i],Format,2,2));
}
}
return Tmp;
}
AnsiString __fastcall RowDataLabelToString(float *OutRowData, int n, AnsiString Label)
{
AnsiString Tmp = Label + "\t" + Label;
for (int i=0; i<n; i++)
{
Tmp += "\t";
if (OutRowData[i] != NODATA)
{
Tmp += AnsiString(OutRowData[i]);
}
}
return Tmp;
}
AnsiString __fastcall RowDataLabelsToString(float *OutRowData, int n, AnsiString IDLabel, AnsiString NameLabel)
{
AnsiString Tmp = IDLabel + "\t" + NameLabel;
for (int i=0; i<n; i++)
{
Tmp += "\t";
if (OutRowData[i] != NODATA)
{
Tmp += AnsiString(OutRowData[i]);
}
}
return Tmp;
}
__fastcall TTableObjectInfo::TTableObjectInfo() : TObject()
{
ID = "";
Name = "";
Group = 1;
Weight = 1;
Order = 1;
}
__fastcall TTableObjectInfo::~TTableObjectInfo()
{
ID = "";
Name = "";
}
void __fastcall TTableObjectInfo::ReadFromStream(TFileStream *Stream)
{
int size;
char *tempstring;
Stream->Read(&size,sizeof(int));
tempstring = new char[size];
Stream->Read(tempstring,size*sizeof(char));
ID = AnsiString(tempstring).SubString(1,size);
delete tempstring;
Stream->Read(&size,sizeof(int));
tempstring = new char[size];
Stream->Read(tempstring,size*sizeof(char));
Name = AnsiString(tempstring).SubString(1,size);
delete tempstring;
Stream->Read(&Group,sizeof(Group));
Stream->Read(&Weight,sizeof(Group));
Stream->Read(&Order,sizeof(Group));
}
void __fastcall TTableObjectInfo::WriteToStream(TFileStream *Stream)
{
int size;
char* tempstring;
tempstring = ID.c_str();
size = ID.Length();
Stream->Write(&size,sizeof(size));
Stream->Write(tempstring,size*sizeof(char));
tempstring = Name.c_str();
size = Name.Length();
Stream->Write(&size,sizeof(size));
Stream->Write(tempstring,size*sizeof(char));
Stream->Write(&Group,sizeof(Group));
Stream->Write(&Weight,sizeof(Group));
Stream->Write(&Order,sizeof(Group));
}
__fastcall TTableData::TTableData() : TObject()
{
}
__fastcall TTableData::~TTableData()
{
for (int Row=0;Row<Rows;Row++)
{
try
{
delete Data[Row];
}
catch (Exception &E)
{
}
try
{
delete RowInfo[Row];
}
catch (Exception &E)
{
}
}
for (int Column=0;Column<Columns;Column++)
{
try
{
delete ColumnInfo[Column];
}
catch (Exception &E)
{
}
}
delete Data;
delete RowInfo;
delete ColumnInfo;
}
void __fastcall TTableData::LoadFromTabFile(AnsiString FileName)
{
// Clear old Data
UpdateUser("Processing File",0);
for (int Row=0;Row<Rows;Row++)
{
delete Data[Row];
delete RowInfo[Row];
}
for (int Column=0;Column<Columns;Column++)
{
delete ColumnInfo[Column];
}
delete Data;
delete RowInfo;
delete ColumnInfo;
// Load file into TStringList
TStringList *List = new TStringList();
List->LoadFromFile(FileName);
// Create TStringList for individual lines of tab-delimited data
TStringList *LineList = new TStringList();
AnsiString Line;
//First Parse Header Line
//It is assumed that first line contains headers
Line = List->Strings[0];
SplitString(&Line,LineList);
IDType = LineList->Strings[0];
int NameIndex = -1;
int WeightIndex = -1;
int GroupIndex = -1;
int OrderIndex = -1;
// Determine column positions of various gene information columns
NameIndex = max(NameIndex,LineList->IndexOf("NAME"));
NameIndex = max(NameIndex,LineList->IndexOf("DESC"));
NameIndex = max(NameIndex,LineList->IndexOf("DESCRIPTION"));
WeightIndex = max(WeightIndex,LineList->IndexOf("WEIGHT"));
WeightIndex = max(WeightIndex,LineList->IndexOf("GWEIGHT"));
GroupIndex = max(GroupIndex,LineList->IndexOf("GROUP"));
GroupIndex = max(GroupIndex,LineList->IndexOf("GROUP"));
OrderIndex = max(OrderIndex,LineList->IndexOf("ORDER"));
OrderIndex = max(OrderIndex,LineList->IndexOf("GORDER"));
// Assume all other columns are data columns
bool* ColumnIsData = new bool[LineList->Count];
for (int Column=0; Column<LineList->Count; Column++)
{
ColumnIsData[Column] = true;
}
// Start out assuming number of data columns = number of columns in header
Columns = LineList->Count;
// The first columns must be ID
ColumnIsData[0] = false;
Columns--;
//Now check the rest of the columns
if (NameIndex > -1)
{
ColumnIsData[NameIndex] = false;
Columns--;
}
if (WeightIndex > -1)
{
ColumnIsData[WeightIndex] = false;
Columns--;
}
if (GroupIndex > -1)
{
ColumnIsData[GroupIndex] = false;
Columns--;
}
if (OrderIndex > -1)
{
ColumnIsData[OrderIndex] = false;
Columns--;
}
// OK Columns is the number of data columns
ColumnInfo = new TTableObjectInfo*[Columns];
int ColumnIndex = 0;
int* InColumn = new int[Columns];
for (int Column=0; Column<LineList->Count; Column++)
{
if (ColumnIsData[Column])
{
ColumnInfo[ColumnIndex] = new TTableObjectInfo();
ColumnInfo[ColumnIndex]->ID = LineList->Strings[Column];
InColumn[ColumnIndex] = Column;
ColumnIndex++;
}
}
bool* RowIsData = new bool[List->Count];
for (int Row=0; Row<List->Count; Row++)
{
RowIsData[Row] = true;
}
Rows = List->Count;
// Subtract 1 for header
RowIsData[0] = false;
Rows--;
// Now do a first pass to figure out which rows have accessory info about
// the columns. If they have such info, load it into ColumnInfo
// Limit search to the first 10 rows
for (int Row=1; Row<10; Row++)
{
Line = List->Strings[Row];
SplitString(&Line,LineList);
// Rows should have a special key in the first column to indicate the
// presence of accessory information about columns
// WEIGHT or EWEIGHT indicate presence of user-defined weight information
// for columns, see manual for details
if ( (LineList->Strings[0] == "WEIGHT") || (LineList->Strings[0] == "EWEIGHT") )
{
Rows--;
RowIsData[Row] = false;
for (int Column=0; Column<Columns; Column++)
{
try
{
double Weight = LineList->Strings[InColumn[Column]].ToDouble();
ColumnInfo[Column]->Weight = Weight;
}
catch (Exception &E)
{
}
}
}
// ORDER or EORDER indicate presence of user-defined order information
// for columns, see manual for details
else if ( (LineList->Strings[0] == "ORDER") || (LineList->Strings[0] == "EORDER") )
{
Rows--;
RowIsData[Row] = false;
for (int Column=0; Column<Columns; Column++)
{
try
{
double Order = LineList->Strings[InColumn[Column]].ToDouble();
ColumnInfo[Column]->Order = Order;
}
catch (Exception &E)
{
}
}
}
// GROUP or EGROUP indicate presence of user-defined group information
// for columns, see manual for details
else if ( (LineList->Strings[0] == "GROUP") || (LineList->Strings[0] == "EGROUP") )
{
Rows--;
RowIsData[Row] = false;
for (int Column=0; Column<Columns; Column++)
{
try
{
int Group = LineList->Strings[InColumn[Column]].ToInt();
ColumnInfo[Column]->Group = Group;
}
catch (Exception &E)
{
}
}
}
// NAME indicate presence of user-defined name for columns
else if ( (LineList->Strings[0] == "NAME") )
{
Rows--;
RowIsData[Row] = false;
for (int Column=0; Column<Columns; Column++)
{
try
{
ColumnInfo[Column]->Name = LineList->Strings[InColumn[Column]];
}
catch (Exception &E)
{
}
}
}
}
// Rows should now be the number of data rows in the file
// Allocate memory for Data and RowInfo and initialize values
Data = new float*[Rows];
RowInfo = new TTableObjectInfo*[Rows];
for (int Row=0; Row<Rows; Row++)
{
RowInfo[Row] = new TTableObjectInfo();
Data[Row] = new float[Columns];
for (int Column=0; Column<Columns; Column++)
{
Data[Row][Column] = NODATA;
}
}
// Now get ready to pass through the file again to load data
int RowIndex = -1;
for (int Row=0; Row<List->Count; Row++)
{
if (RowIsData[Row] == true)
{
RowIndex++;
UpdateUser("Loading Row " + AnsiString(RowIndex+1) + " of " + AnsiString(Rows),1);
Line = List->Strings[Row];
SplitString(&Line,LineList);
RowInfo[RowIndex]->ID = LineList->Strings[0];
// If any of the columns represent accessory information for the
// rows, get these values and store in RowInfo
if (NameIndex > 0)
{
try
{
AnsiString Name = LineList->Strings[NameIndex];
RowInfo[RowIndex]->Name = Name;
}
catch (Exception &E)
{
}
}
if (WeightIndex > 0)
{
try
{
double Weight = LineList->Strings[WeightIndex].ToDouble();
RowInfo[RowIndex]->Weight = Weight;
}
catch (Exception &E)
{
}
}
if (GroupIndex > 0)
{
try
{
int Group = LineList->Strings[GroupIndex].ToInt();
RowInfo[RowIndex]->Group = Group;
}
catch (Exception &E)
{
}
}
if (OrderIndex > 0)
{
try
{
double Order = LineList->Strings[OrderIndex].ToDouble();
RowInfo[RowIndex]->Order = Order;
}
catch (Exception &E)
{
}
}
// Now get the data
for (int Column=0; Column<Columns; Column++)
{
try
{
if (InColumn[Column] < LineList->Count)
{
if (LineList->Strings[InColumn[Column]].Length() > 0)
{
// should throw an exception here if there was any
// problem getting the data from the appropriate string
// this will include conversion errors and access errors
// if there are not enough strings in the list
float Val = LineList->Strings[InColumn[Column]].ToDouble();
// if we get this far then store Val in the appropriate
// place in the Data matrix
Data[RowIndex][Column] = Val;
}
}
}
catch (Exception &E)
{
}
}
}
}
delete List;
delete LineList;
delete RowIsData;
delete ColumnIsData;
delete InColumn;
}
/* SaveToTableFile
Borland C++ Builder specific routing to save to tab-delmited text file
*/
void __fastcall TTableData::SaveToTabFile(AnsiString FileName)
{
TStringList *OutList = new TStringList();
OutList->Add(RawHeader());
for (int row=0; row<Rows; row++)
{
OutList->Add(RawRowString(row));
}
OutList->SaveToFile(FileName);
}
void __fastcall TTableData::SaveToBinaryFile(AnsiString FileName)
{
UpdateUser("Processing File",0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -