//--------------------------------------------------------------------------- #include #pragma hdrstop USERES("ScanVolt.res"); USEFORM("FileManager.cpp", FileScreen); USEFORM("EndingScreen.cpp", ProgressScreen); USEFORM("LastScreen.cpp", ReviewScreen); USEFORM("ListFile.cpp", ListFileForm); USEFORM("NextScreen.cpp", AnalysisInput); //--------------------------------------------------------------------------- WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { try { Application->Initialize(); Application->Title = "ScanVolt"; Application->CreateForm(__classid(TFileScreen), &FileScreen); Application->CreateForm(__classid(TProgressScreen), &ProgressScreen); Application->CreateForm(__classid(TReviewScreen), &ReviewScreen); Application->CreateForm(__classid(TListFileForm), &ListFileForm); Application->CreateForm(__classid(TAnalysisInput), &AnalysisInput); Application->Run(); } catch (Exception &exception) { Application->ShowException(&exception); } return 0; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include #include "FileManager.h" #include "ListFile.h" #include "NextScreen.h" #include "LastScreen.h" #include "EndingScreen.h" #pragma hdrstop //--------------------------------------------------------------------------- #pragma resource "*.dfm" TFileScreen *FileScreen; bool MLBUTTON = false; String MainDir; //--------------------------------------------------------------------------- __fastcall TFileScreen::TFileScreen(TComponent* Owner) : TForm(Owner) { MainDir = FileScreen->DirectoryListBox1->Directory + "\\"; } //--------------------------------------------------------------------------- void __fastcall TFileScreen::FileScreenExitClick(TObject *Sender) { FileScreen->Close(); } //--------------------------------------------------------------------------- void __fastcall TFileScreen::FileListBox1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { if (Button != mbLeft) { return; } if (MLBUTTON == true) { MLBUTTON = false; return; } if (FileListBox1->ItemAtPos (Point (X,Y), true) >= 0) { FileListBox1->BeginDrag (false, 1); return; } } //--------------------------------------------------------------------------- void __fastcall TFileScreen::ListBox1DragOver(TObject *Sender, TObject *Source, int X, int Y, TDragState State, bool &Accept) { // Only accept a drop from the file list box if (Source == FileListBox1) { Accept = true;} else { Accept = false; return; } // Don't accept same file twice.... int limit = NumberOfFiles(ListBox1->Items->Count); if (limit == 0) { Accept = true; return;} for (int i=0; i < limit; i++) { if (ListBox1->Items->Strings[i] == FileListBox1->Items->Strings[FileListBox1->ItemIndex]) { Accept = false; return; } } Accept = true; return; } //--------------------------------------------------------------------------- void __fastcall TFileScreen::ListBox1DragDrop(TObject *Sender, TObject *Source, int X, int Y) { ListBox1->Items->Add(FileListBox1->Items->Strings[FileListBox1->ItemIndex]); FileCounter(); if (ListBox1->Items->Count > 0) { Start->Enabled = true; } } //--------------------------------------------------------------------------- void __fastcall TFileScreen::ClearLISTClick(TObject *Sender) { TListBox &temp = *ListBox1; temp.Clear(); FileCounter(); Start->Enabled = false; } //************************************* int TFileScreen::NumberOfFiles(String buff) { int FileNum; FileNum = buff.ToInt(); return FileNum; } //***************************************** void TFileScreen::FileCounter() { Counter->Text = AnsiString(" ") + ListBox1->Items->Count; } //--------------------------------------------------------------------------- void __fastcall TFileScreen::ClearLASTClick(TObject *Sender) { int last = (NumberOfFiles(ListBox1->Items->Count) - 1); ListBox1->Items->Delete(last); FileCounter(); if (last == 0) { Start->Enabled = false;} } //----------------------------------------------------------- void TFileScreen::DisplayFile() { String filename; filename = FileListBox1->Items->Strings[FileListBox1->ItemIndex]; ListFileForm->FileName->Text = filename; ListFileForm->OutBox->Lines->LoadFromFile(filename); ListFileForm->ShowModal(); } //--------------------------------------------------------------------------- void __fastcall TFileScreen::StartClick(TObject *Sender) { // Advance to Analysis Input Screen AnalysisInput->Show(); } //--------------------------------------------------------------------------- void __fastcall TFileScreen::FormShow(TObject *Sender) { // . . . . . . . } //--------------------------------------------------------------------------- void __fastcall TFileScreen::FormMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { // function clears mouse double-click FileCounter(); } //--------------------------------------------------------------------------- void __fastcall TFileScreen::FileListBox1DblClick(TObject *Sender) { DisplayFile(); MLBUTTON = true; } //--------------------------------------------------------------------------- void __fastcall TFileScreen::Button1Click(TObject *Sender) { int FileLimit = NumberOfFiles(FileListBox1->Items->Count); for (int i=0; i < FileLimit; i++) { ListBox1->Items->Strings[i] = FileListBox1->Items->Strings[i]; } FileCounter(); if (ListBox1->Items->Count > 1) { Start->Enabled = true; } } //--------------------------------------------------------------------------- void __fastcall TFileScreen::FormClose(TObject *Sender, TCloseAction &Action) { Application->Terminate(); } //--------------------------------------------------------------------------- void __fastcall TAnalysisInput::BackClick(TObject *Sender) { AnalysisInput->Close(); } //--------------------------------------------------------------------------- void __fastcall TProgressScreen::STARTOVERClick(TObject *Sender) { ProgressScreen->Close(); ReviewScreen->Close(); AnalysisInput->Close(); } //--------------------------------------------------------------------------- void __fastcall TProgressScreen::EXITClick(TObject *Sender) { ProgressScreen->Close(); ReviewScreen->Close(); AnalysisInput->Close(); FileScreen->Close(); } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include #include "ListFile.h" #pragma hdrstop //--------------------------------------------------------------------------- #pragma resource "*.dfm" TListFileForm *ListFileForm; //--------------------------------------------------------------------------- __fastcall TListFileForm::TListFileForm(TComponent* Owner) : TForm(Owner) { } //---------------------------------------------------- void __fastcall TListFileForm::ReturnFileListClick(TObject *Sender) { Close(); } //--------------------------------------------------------------------------- void __fastcall TListFileForm::FormClose(TObject *Sender, TCloseAction &Action) { //Action = caHide; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include #include #pragma hdrstop #include "NextScreen.h" #include "LastScreen.h" #include "FileManager.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TAnalysisInput *AnalysisInput; String other_species; bool omit_1_scan, Extract_File_Name, Extract_Date, Extract_Time, Extract_Aux2; int smoothing_points; int number_replicates; float ViO2, VfO2, ViH2O2, VfH2O2, ViHS, VfHS, ViFeS, VfFeS, ViOther, VfOther; //--------------------------------------------------------------------------- __fastcall TAnalysisInput::TAnalysisInput(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TAnalysisInput::NextClick(TObject *Sender) { if (ComboBox1->ItemIndex == 1) { smoothing_points = Edit13->Text.ToInt(); } else { smoothing_points = 1;} number_replicates = Edit1->Text.ToInt(); // need to be able to make the Vi & Vo values accept negative, decimal inputs. if (CheckBox7->Checked) { ViO2 = StrToFloat(AnsiString(Edit2->Text)); VfO2 = StrToFloat(AnsiString(Edit3->Text)); } // do I need these else statements since if checkbox isn't checked, we won't need Vi & Vf else { ViO2 = 0; VfO2 = 0; } if (CheckBox8->Checked) { ViH2O2 = Edit4->Text.ToInt(); VfH2O2 = Edit5->Text.ToInt(); } else { ViH2O2 = 0; VfH2O2 = 0; } if (CheckBox9->Checked) { ViHS = Edit6->Text.ToInt(); VfHS = Edit7->Text.ToInt(); } else { ViHS = 0; VfHS = 0; } if (CheckBox9->Checked) { ViFeS = Edit8->Text.ToInt(); VfFeS = Edit9->Text.ToInt(); } else { ViFeS = 0; VfFeS = 0; } other_species = Edit10->Text; if (CheckBox10->Checked) { ViOther = Edit11->Text.ToInt(); VfOther = Edit12->Text.ToInt(); } else { ViOther = 0; VfOther = 0; } // going on to show requested components on ReviewScreen... ReviewScreen->number_Replicates->Caption = AnalysisInput->Edit1->Text; ReviewScreen->Omit_First->Caption = AnalysisInput->Edit14->Text; int variable = smoothing_points*2+1; ReviewScreen->Smoothing_Num->Caption = AnsiString(variable); for (int i=0; i< FileScreen->ListBox1->Items->Count; i++) { ReviewScreen->ListBox1->Items->Add(FileScreen->ListBox1->Items->Strings[i]); } ReviewScreen->Show(); } //--------------------------------------------------------------------------- void __fastcall TAnalysisInput::FormShow(TObject *Sender) { FileScreen->WindowState = wsMinimized; } //--------------------------------------------------------------------------- void __fastcall TAnalysisInput::Edit1Change(TObject *Sender) { if (Edit1->Text.ToInt()>20 && Edit1->Text !='0') { Edit1->Text=20;} } //--------------------------------------------------------------------------- void __fastcall TAnalysisInput::Edit14Change(TObject *Sender) { if (Edit14->Text.ToInt()>=Edit1->Text.ToInt() && Edit14->Text != '0') { Application->MessageBox( "Number of scans to ignore MUST be less than the number of replicates.","Error", MB_OK); } } //--------------------------------------------------------------------------- void __fastcall TAnalysisInput::ComboBox1Change(TObject *Sender) { if (ComboBox1->ItemIndex ==0) {Edit13->Text='0';} } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include #include #include #include #include #include #include #include "LastScreen.h" #include "NextScreen.h" #include "FileManager.h" #pragma hdrstop //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TReviewScreen *ReviewScreen; double Current[10000]; double CurrentRaw[10000]; //input data array double Volt[10000]; //input data array int DataCount; //input data counter double O2Current; String FileName, FileDate, FileHHMMSS, FileAMPM, FileTime, FileScanRate, FileAux2; String OutputFileName; String HHMM; bool Peak1Found = false; bool Peak2Found = false; float Fpeak = 0; float Ipeak = 0; float VoltBase = 0; float VoltPeak = 0; //--------------------------------------------------------------------------- __fastcall TReviewScreen::TReviewScreen(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TReviewScreen::StartOverClick(TObject *Sender) { ReviewScreen->Close(); AnalysisInput->Close(); FileScreen->WindowState = wsNormal; } //--------------------------------------------------------------------------- void __fastcall TReviewScreen::RunClick(TObject *Sender) { // start program thread for file analysis ReviewScreen->WindowState = wsNormal; EndProgram->Enabled = true; RedDog = new TRedDog; } //--------------------------------------------------------------------------- // RedDog is the TThread with the file analysis routines //--------------------------------------------------------------------------- __fastcall TRedDog::TRedDog(void) : TThread(true) { FreeOnTerminate = true; Priority = tpHigher; Resume(); } //----------------------------------------------------------------------------- void __fastcall TRedDog::Execute(void) {//Start RedDog Thread . . . . . . . . . char Istring[20], Fstring[20], O2string[20], AVGstring[20], SDstring[20], SEstring[20]; String RepTime; TimeStamp(); //get time and store in HHMM int FileCount = FileScreen->ListBox1->Items->Count; int RepLoop; double RepMean, RepSD, RepSE, RepData[20]; int Replicates = AnalysisInput->Edit1->Text.ToInt(); int RepDrop = AnalysisInput->Edit14->Text.ToInt(); int N = Replicates-RepDrop; OutputFileName = FileScreen->DirectoryListBox1->Directory + "\\" + "ScanVoltSummary.txt"; ofstream BlueCat(OutputFileName.c_str()); OutputFileName = FileScreen->DirectoryListBox1->Directory + "\\" + "ScanVoltPlot.txt"; ofstream GreenCat(OutputFileName.c_str()); BlueCat << "Scan Volt Summary Analysis (V 1.01) " << HHMM.c_str() << endl; BlueCat << endl; /*BlueCat << "This program was designed by B. Glazer and A. Marsh to open sequential" << endl; BlueCat << " voltammetry scans and identify the signal peaks or features necessary" << endl; BlueCat << " for extracting concentration information about a redox species." << endl; BlueCat << "` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `" << endl; */ BlueCat << endl; BlueCat << "Data output for: " << FileScreen->DirectoryListBox1->Directory.c_str() << endl; BlueCat << "Input variables for analysis:" << endl; BlueCat << " Moving average window (+/-): " << AnalysisInput->Edit13->Text.c_str() << endl; BlueCat << " Number of replicates: " << AnalysisInput->Edit1->Text.c_str() << endl; BlueCat << " Ignore first x replicate(s): x =" << AnalysisInput->Edit14->Text.c_str() << endl; if (AnalysisInput->CheckBox7->Checked) { BlueCat << " Oxygen - Vi: " << AnalysisInput->Edit2->Text.c_str() << " Vf: " << AnalysisInput->Edit3->Text.c_str() << endl; } BlueCat << endl; BlueCat << "==========================================================================================" << endl; BlueCat << "File Name Date Time AUX2 Vi Vf O2(na) AVG SD SE status" << endl; BlueCat << "------------------------------------------------------------------------------------------" << endl; // Here's where the cycle starts . . . . . . . . . RepLoop = 1; for (int xFileIn =0; xFileIn < FileCount; xFileIn++) { if (RepLoop > Replicates) { RepLoop =1; } // set all array data to zero for (int i=0; i<9999; i++) { Current[i]=Current[i]-Current[i]; Volt[i]=Volt[i]-Volt[i]; CurrentRaw[i]=CurrentRaw[i]-CurrentRaw[i]; } // Job 1: Open next file and input data into variable arrays FileInput(xFileIn); if (FileName != "Not scan data file") { // Job 2: Update output file BlueCat << FileName.c_str() << " " << FileDate.c_str() << " " << FileTime.c_str() << " " << FileScanRate.c_str() << " " << FileAux2.c_str() << " "; if (2*RepLoop > (Replicates-RepDrop)) { RepTime = FileTime; } // Job 3: Data manipulation and calculation if (AnalysisInput->CheckBox7->Checked == true) { float Vi = StrToFloat(AnsiString(AnalysisInput->Edit2->Text)); float Vf = StrToFloat(AnsiString(AnalysisInput->Edit3->Text)); O2Current = DataProcess(Vi, Vf); } if (RepLoop > RepDrop) //setup of array of replicate measurements { RepData[RepLoop-RepDrop-1] = O2Current; } if (RepLoop == Replicates) { RepMean = 0; RepSD = 0; RepSE = 0; for (int x=0; xMemo1->Lines->Add(FileName + " " + AnsiString(SigDigits(O2Current))); // Job 5: Format and output results to file // Go Back and get the next data set }//end if !FileName = "Not scan data file" else { ReviewScreen->Memo1->Lines->Add(FileName); } RepLoop++; }//end of for xFileIn loop // Job 6: Omit requested scans & average replicates BlueCat.close(); ReviewScreen->Memo1->Lines->Add(" "); ReviewScreen->Memo1->Lines->Add("Job Complete"); }//end of RedDog TThread................. //------------------------------------------------------------------ void TRedDog::FileInput(int FileNum) { bool found = false; char flag[10]; char RawInput[20]; double CurrentIn, VoltIn; String FirstWord; int L; FileName = "Not scan data file"; // Define the current input filename String sFile = FileScreen->DirectoryListBox1->Directory + "\\" + FileScreen->ListBox1->Items->Strings[FileNum]; // Open the current input file for data stream ifstream InputFile(sFile.c_str()); // Check for valid DataFile ------------------------------- InputFile >> RawInput; FirstWord.SetLength(20); L = sprintf(FirstWord.c_str(), RawInput); FirstWord.SetLength(L); if (FirstWord == "AIS") { InputFile.ignore(100,'\n'); // Find Name ---------------------------------------------- for (int iLines = 0; iLines < 3; iLines++) { InputFile.ignore(100,'\n'); } found = false; while (!found) { InputFile >> flag[0]; if (flag[0] == ':') { found = true; } } InputFile >> RawInput; FileName.SetLength(20); L = sprintf(FileName.c_str(), RawInput); FileName.SetLength(L); // Find Date ---------------------------------------------- for (int iLines = 0; iLines < 0; iLines++) { InputFile.ignore(100,'\n'); } found = false; while (!found) { InputFile >> flag[0]; if (flag[0] == ':') { found = true; } } InputFile >> RawInput; FileDate.SetLength(20); L = sprintf(FileDate.c_str(), RawInput); FileDate.SetLength(L); // Find Time --------------------------------------------- for (int iLines = 0; iLines < 0; iLines++) { InputFile.ignore(100,'\n'); } found = false; while (!found) { InputFile >> flag[0]; if (flag[0] == ':') { found = true; } } InputFile >> RawInput; FileHHMMSS.SetLength(20); L = sprintf(FileHHMMSS.c_str(), RawInput); FileHHMMSS.SetLength(L); InputFile >> RawInput; FileAMPM.SetLength(20); L = sprintf(FileAMPM.c_str(), RawInput); FileAMPM.SetLength(L); FileTime = FileHHMMSS + " " + FileAMPM; // Find ScanRate ---------------------------------- for (int iLines = 0; iLines < 21; iLines++) { InputFile.ignore(100,'\n'); } found = false; while (!found) { InputFile >> flag[0]; if (flag[0] == ':') { found = true; } } InputFile >> RawInput; FileScanRate.SetLength(20); L = sprintf(FileScanRate.c_str(), RawInput); FileScanRate.SetLength(L); // Find AUX2 ---------------------------------- for (int iLines = 0; iLines < 27; iLines++) { InputFile.ignore(100,'\n'); } found = false; while (!found) { InputFile >> flag[0]; if (flag[0] == ':') { found = true; } } InputFile >> RawInput; FileAux2.SetLength(20); L = sprintf(FileAux2.c_str(), RawInput); FileAux2.SetLength(L); // Data Input -------------------------------------- for (int iLines = 0; iLines < 4; iLines++) { InputFile.ignore(100,'\n'); } DataCount = 0; while (!InputFile.eof()) { InputFile >> VoltIn >> CurrentIn; Volt[DataCount] = VoltIn*-1; //use positive values CurrentRaw[DataCount] = SigDigits(CurrentIn*1000000000);//convert to nanoamps DataCount += 1; } DataCount -= 1; Current[9999] = 666; // Data smoothing -------------------------------- double CurrentSum; int smoothing_points = AnalysisInput->Edit13->Text.ToInt(); // if (AnalysisInput->ComboBox1->Items->Strings == 'moving average') int v; for (int i=0; iEdit13->Text.ToInt(); int smoothing_points = 10; I_index = 9999; //value flag for error Fpeak = 0; Ipeak = 1000; VoltPeak = 0; VoltBase = 0; Peak1Found = false; Peak2Found = false; // Look for peak max (Vf) i = 0; while (Volt[i] < fstart) { i++; } StartIndex = i; while (Volt[i] < fstop) { if (Current[i] > Current[i+1]) { Peak1Found = true; if (Current[i] > Fpeak) { Fpeak = Current[i]; VoltPeak = Volt[i];} } i++; }// end while /* No Peak found ? . . . Locate the Current[i] value at the flatest part of the curve near Vf. Find the [i] position where the sum of squares of the differences between ith observation is minimized across the 'smoothing' window. Returns mid-point of the window as Current[i]. */ if (!Peak1Found) { i = StartIndex; while (Volt[i] < fstop) { diff1 = 0; diff2 = 1000000000; for (int j=0; j <= ((2*smoothing_points)+1); j++) { diff1 += (Sqr(Current[(i-smoothing_points)+j]- Current[(i-smoothing_points)+j+1])); }// end for j if (diff1 < diff2) { diff2 = diff1; //store lowest sum of squares I_index = i; //store i position of low sos. // could return the starting ith obs as: i-smoothing_points }// end if i++; }// end while Fpeak = Current[I_index]; //on error, Fpeak will equal 666 VoltPeak = Volt[I_index]; } // end if !Peak1Found // Look for peak min (Vi) I_index = 9999; // error flag value i = 0; if (Volt[i] < istart) { while (Volt[i] < istart) { i++;} } StartIndex = i; while (Volt[i] < istop) { if (Current[i] > Current[i+1]) { Peak2Found = true; if (Current[i+1] < Ipeak) { Ipeak = Current[i+1]; VoltBase = Volt[i+1];} } i++; }// end while /* The comparison below is designed to find an inflection point by looking for the greatest difference in SOS between two areas of the data curve: at the ith position, the comparison is between the i+smoothing_points and the i-smoothing_points values. */ if (!Peak2Found) { if (StartIndex > smoothing_points) { i = StartIndex; } else { i = smoothing_points; } diff1 = 0; diff2 = 0; while (Volt[i] < istop) { double GoingUp = 0; double GoingDown = 0; for (int j=1; j <= smoothing_points; j++) { GoingDown += Sqr(Current[i-j] - Current[i]); GoingUp += Sqr(Current[i+j] - Current[i]); }// end for j diff1 = Sqr(GoingUp - GoingDown); if (diff1 > diff2) { diff2 = diff1; I_index = i; }// end if i++; }// end while Ipeak = Current[I_index]; // on error Ipeak will equal 666 VoltBase = Volt[I_index]; }//end if !Peak2Found return Fpeak - Ipeak; } //------------------------------------------------------------------ double TRedDog::Sqr(double x) { x = x*x; return x; } //--------------------------------------------------------------------------- void TRedDog::TimeStamp() { SYSTEMTIME time; GetLocalTime (&time); HHMM.SetLength(64); int L = GetTimeFormat (LOCALE_USER_DEFAULT, 0, &time, NULL, HHMM.c_str(),HHMM.Length()); HHMM.SetLength(L); return; } //--------------------------------------------------------------------------- double TRedDog::SigDigits(double NanoAmps) { double SignificantDigits; NanoAmps = NanoAmps*10000; SignificantDigits = ceil(NanoAmps); SignificantDigits = SignificantDigits/10000; return SignificantDigits; } //---------------------------------------------------------------------------- void __fastcall TReviewScreen::EndProgramClick(TObject *Sender) { RedDog->Terminate(); ReviewScreen->Close(); AnalysisInput->Close(); FileScreen->Close(); } //--------------------------------------------------------------------------- void __fastcall TReviewScreen::FormShow(TObject *Sender) { AnalysisInput->WindowState = wsMinimized; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include #pragma hdrstop #include "EndingScreen.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TProgressScreen *ProgressScreen; //--------------------------------------------------------------------------- __fastcall TProgressScreen::TProgressScreen(TComponent* Owner) : TForm(Owner) { } //---------------------------------------------------------------------------