#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "FSUDAQ.h" long get_time(){ long time_ms; struct timeval t1; struct timezone tz; gettimeofday(&t1, &tz); time_ms = (t1.tv_sec) * 1000 + t1.tv_usec / 1000; return time_ms; } Double_t traceFunc(Double_t *x, Double_t *par){ ///par[0] = baseline ///par[1] = start time ///par[2] = rise time ///par[3] = Amp ///par[4] = decay time Double_t result = par[0]; if(x[0] > par[1]){ Double_t y = x[0]-par[1]; result += par[3] *(1 - TMath::Exp( - y / par[2])) * TMath::Exp(-y / par[4]); } return result; } ///============= Global variable TH1F * hEnergy[MaxNBoards][MaxNChannels] = {NULL}; TH1F * hChannel[MaxNBoards] = {NULL}; TGraph * gDummy = NULL; /// this is a dummy TGraph to set the plot range TGraph * gAnaTrace1 = NULL ; TGraph * gAnaTrace2 = NULL ; TGraph * gDigiTrace1 = NULL ; TGraph * gDigiTrace2 = NULL ; Pixel_t red, blue, green; unsigned short nDigi; Digitizer ** digi = NULL; unsigned short lastRunID; ///============ static members TGTextEdit * MainWindow::teLog = NULL; TRootEmbeddedCanvas * MainWindow::fEcanvas = NULL; TGNumberEntry * MainWindow::boardIDEntry = NULL; TGNumberEntry * MainWindow::chIDEntry = NULL; TGComboBox* MainWindow::cbMode = NULL; TGTextEntry * MainWindow::dataPrefix = NULL; TGNumberEntry * MainWindow::runIDEntry = NULL; TGCheckButton * MainWindow::cbDataRun = NULL; BoardSetting * MainWindow::boardSetting = NULL; enum MenuIdentifiers{ M_DIGITIZER_OPEN, M_FILE_OPEN, M_EXIT, M_LOAD_SETTINGS, M_TRIGGER_SUMMARY, M_CH_SETTING_PHA, M_CH_SETTING_PSD, M_REGISTER_SETTING, M_BOARD_SETTINGS, M_PROGRAM_SETTINGS, M_FINDPEAKS }; enum ModeIdentifiers{ Mode_EnergyHist, Mode_CountHist, Mode_Oscilloscope, }; MainWindow::MainWindow(const TGWindow *p,UInt_t w,UInt_t h) { printf("----- %s \n", __func__); nDigi = 0; gClient->GetColorByName("red", red); gClient->GetColorByName("blue", blue); gClient->GetColorByName("green", green); /// Create a main frame fMain = new TGMainFrame(p,w,h); ///fMain->SetWMPosition(500, 500); //does not work fMain->Connect("CloseWindow()", "MainWindow", this, "GoodBye()"); {///======================= menu fMenuBar = new TGMenuBar(fMain, 1, 1, kHorizontalFrame); fMain->AddFrame(fMenuBar, new TGLayoutHints(kLHintsTop | kLHintsExpandX)); fMenuFile = new TGPopupMenu(gClient->GetRoot()); fMenuFile->AddEntry("&Open File", M_FILE_OPEN); fMenuFile->AddSeparator(); fMenuFile->AddEntry("E&xit", M_EXIT); fMenuFile->Connect("Activated(Int_t)", "MainWindow", this, "HandleMenu(Int_t)"); fMenuBar->AddPopup("&File", fMenuFile, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0)); fMenuDigitizers = new TGPopupMenu(gClient->GetRoot()); fMenuDigitizers->AddEntry("&Open Digitizers", M_DIGITIZER_OPEN); fMenuDigitizers->AddEntry("&Load Setting (Offline)", M_LOAD_SETTINGS); fMenuDigitizers->AddEntry("&Trigger Summary", M_TRIGGER_SUMMARY); fMenuDigitizers->AddSeparator(); fMenuDigitizers->AddEntry("Digitizer &Settings", M_BOARD_SETTINGS); fMenuDigitizers->AddEntry("&Channel Settings (PHA)", M_CH_SETTING_PHA); fMenuDigitizers->AddEntry("&Channel Settings (PSD)", M_CH_SETTING_PSD); fMenuDigitizers->AddEntry("&Register Setting", M_REGISTER_SETTING); fMenuDigitizers->AddSeparator(); fMenuDigitizers->AddEntry("&Program Settings", M_PROGRAM_SETTINGS); fMenuDigitizers->Connect("Activated(Int_t)", "MainWindow", this, "HandleMenu(Int_t)"); fMenuBar->AddPopup("&Digitizers", fMenuDigitizers, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0)); fMenuDigitizers->DisableEntry( M_TRIGGER_SUMMARY); fMenuDigitizers->DisableEntry( M_BOARD_SETTINGS); fMenuDigitizers->DisableEntry( M_CH_SETTING_PHA); fMenuDigitizers->DisableEntry( M_CH_SETTING_PSD); fMenuDigitizers->DisableEntry( M_REGISTER_SETTING); fMenuUtility = new TGPopupMenu(gClient->GetRoot()); //fMenuDigitizers->AddSeparator(); fMenuUtility->AddEntry("Find &Peaks", M_FINDPEAKS); fMenuUtility->Connect("Activated(Int_t)", "MainWindow", this, "HandleMenu(Int_t)"); fMenuBar->AddPopup("&Utility", fMenuUtility, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0)); } TGLayoutHints * uniLayoutHints = new TGLayoutHints(kLHintsNormal, 2,2,10,0); ///left, right, top, bottom TGLayoutHints * hahaLayoutHints = new TGLayoutHints(kLHintsNormal, 2,2,15,0); ///left, right, top, bottom TGLayoutHints * haha = new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 2, 2, 10, 0); ///left, right, top, bottom TGHorizontalFrame *hframe = new TGHorizontalFrame(fMain); fMain->AddFrame(hframe, new TGLayoutHints(kLHintsCenterX,2,2,2,2)); {///================= Create a horizontal frame widget with buttons TGGroupFrame * group0 = new TGGroupFrame(hframe, "Run Control", kVerticalFrame); hframe->AddFrame(group0); TGVerticalFrame * vframe = new TGVerticalFrame(group0); group0->AddFrame(vframe); TGHorizontalFrame *hfg0 = new TGHorizontalFrame(vframe); vframe->AddFrame(hfg0 ,new TGLayoutHints(kLHintsLeft, 0, 0, 0, 0)); bOpenDigitizers = new TGTextButton(hfg0,"Open Digitizers"); hfg0->AddFrame(bOpenDigitizers, uniLayoutHints); bOpenDigitizers->Connect("Clicked()","MainWindow",this,"OpenDigitizers()"); bStartRun = new TGTextButton(hfg0,"Start Run"); hfg0->AddFrame(bStartRun, uniLayoutHints); bStartRun->Connect("Clicked()", "MainWindow", this, "StartRun()"); bStartRun->SetEnabled(false); bStopRun = new TGTextButton(hfg0,"Stop Run"); hfg0->AddFrame(bStopRun, uniLayoutHints); bStopRun->Connect("Clicked()", "MainWindow", this, "StopRun()"); bStopRun->SetEnabled(false); TGLabel * lbMode = new TGLabel(hfg0, "Mode"); hfg0->AddFrame(lbMode, hahaLayoutHints); cbMode = new TGComboBox(hfg0); hfg0->AddFrame(cbMode, uniLayoutHints); cbMode->AddEntry("Energy Hist.", Mode_EnergyHist); cbMode->AddEntry("Count Hist.", Mode_CountHist); cbMode->AddEntry("Ocsilloscope.", Mode_Oscilloscope); cbMode->Select(Mode_Oscilloscope, false); cbMode->Resize(80, 20); cbMode->Connect("Changed()", "MainWindow", this, "ChangePlot()"); TGHorizontalFrame *hfg1 = new TGHorizontalFrame(vframe); vframe->AddFrame(hfg1 ,new TGLayoutHints(kLHintsLeft, 0, 0, 0, 0)); TGLabel * lbDataPath = new TGLabel(hfg1, "Save Data Prefix"); hfg1->AddFrame(lbDataPath, hahaLayoutHints); dataPrefix = new TGTextEntry(hfg1, ProgramSetting::ExpName.c_str()); hfg1->AddFrame(dataPrefix,uniLayoutHints); dataPrefix->SetEnabled(false); dataPrefix->Resize(100, 20); TGLabel * lbRunNum = new TGLabel(hfg1, "Run"); hfg1->AddFrame(lbRunNum, hahaLayoutHints); runIDEntry = new TGNumberEntry(hfg1, 0, 0, 0, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative); hfg1->AddFrame(runIDEntry, uniLayoutHints); runIDEntry->SetNumber(lastRunID, false); runIDEntry->SetWidth(50); cbDataRun = new TGCheckButton(hfg1, "Data Run", 1); hfg1->AddFrame(cbDataRun, hahaLayoutHints); cbDataRun->SetState(kButtonUp); TGHorizontalFrame *hfg2 = new TGHorizontalFrame(vframe); vframe->AddFrame(hfg2 ,new TGLayoutHints(kLHintsLeft, 0, 0, 0, 0)); } {///================= single Channel group TGGroupFrame * group1 = new TGGroupFrame(hframe, "Single Channel", kHorizontalFrame); hframe->AddFrame(group1, new TGLayoutHints(kLHintsExpandY)); TGHorizontalFrame *hfg1 = new TGHorizontalFrame(group1,200,30); group1->AddFrame(hfg1 ,new TGLayoutHints(kLHintsLeft, 0, 0, 0, 0)); TGLabel * lb0 = new TGLabel(hfg1, "Board"); hfg1->AddFrame(lb0, haha); boardIDEntry = new TGNumberEntry(hfg1, 0, 0, 0, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative); hfg1->AddFrame(boardIDEntry, haha); boardIDEntry->SetWidth(50); boardIDEntry->SetState(false); boardIDEntry->Connect("Modified()", "MainWindow", this, "ChangeBoard()"); TGLabel * lb1 = new TGLabel(hfg1, "Channel"); hfg1->AddFrame(lb1, haha); chIDEntry = new TGNumberEntry(hfg1, 0, 0, 0, TGNumberFormat::kNESInteger, TGNumberFormat::kNEAAnyNumber); hfg1->AddFrame(chIDEntry, haha); chIDEntry->SetWidth(50); chIDEntry->SetState(false); chIDEntry->Connect("Modified()", "MainWindow", this, "ChangePlot()"); bPlotSingleTrace = new TGTextButton(hfg1,"Plot Trace"); hfg1->AddFrame(bPlotSingleTrace, haha); bPlotSingleTrace->Connect("Clicked()", "MainWindow", this, "PlotSingleTrace()"); bPlotSingleTrace->SetEnabled(false); bFitTrace = new TGTextButton(hfg1,"Fit Trace"); hfg1->AddFrame(bFitTrace, haha); bFitTrace->Connect("Clicked()", "MainWindow", this, "FitTrace()"); bFitTrace->SetEnabled(false); } {///================= canvas widget fEcanvas = new TRootEmbeddedCanvas("Ecanvas",fMain,900,400); fMain->AddFrame(fEcanvas, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,10)); } {///================= Log massage TGGroupFrame * groupLog = new TGGroupFrame(fMain, "Log Message", kHorizontalFrame); fMain->AddFrame(groupLog, new TGLayoutHints(kLHintsExpandX, 10,10,10,10) ); teLog = new TGTextEdit(groupLog, w, 100); groupLog->AddFrame(teLog, new TGLayoutHints(kLHintsExpandX, 2,2,10,0) ); } /// Set a name to the main frame fMain->SetWindowName("FSU DAQ"); /// Map all subwindows of main frame fMain->MapSubwindows(); /// Initialize the layout algorithm fMain->SetWMPosition(200, 200); //does not work?? fMain->Resize(fMain->GetDefaultSize()); /// Map main frame fMain->MapWindow(); /// setup thread runThread = new TThread("kakaka", Run, (void *) 1); boardSetting = NULL; channelSettingPHA = NULL; channelSettingPSD = NULL; registerSetting = NULL; triggerSummary = NULL; programSetting = NULL; LogMsg((char*)"The LogMsg is not complete for all actions. [update later]"); LogMsg((char*)"Please \"Program Setting\" to set data folder"); LogMsg((char*)"Please \"Open Digitizers\" to start."); LogMsg((char*)"OR. \"Load Setting (Offline)\" for inspecting setting file."); //HandleMenu(M_DIGITIZER_OPEN); //HandleMenu(M_BOARD_SETTINGS); //HandleMenu(M_CH_SETTING_PHA); //HandleMenu(M_CH_SETTING_PSD); //HandleMenu(M_REGISTER_SETTING); //HandleMenu(M_TRIGGER_SUMMARY); //HandleMenu(M_PROGRAM_SETTINGS); gDummy = new TGraph(); gDummy->SetPoint(0, 0, 0); /// the lower left corner gDummy->GetXaxis()->SetTitle("[ns]"); gAnaTrace1 = new TGraph(); gAnaTrace1->SetName("Analog Trace 1"); gAnaTrace1->GetXaxis()->SetTitle("[ns]"); gAnaTrace2 = new TGraph(); gAnaTrace2->SetName("Analog Trace 2"); gAnaTrace2->SetLineColor(2); gDigiTrace1 = new TGraph(); gDigiTrace1->SetName("Digital Trace 1"); gDigiTrace1->SetLineColor(4); gDigiTrace2 = new TGraph(); gDigiTrace2->SetName("Digital Trace 2"); gDigiTrace2->SetLineColor(6); gStyle->SetOptStat("neiou"); DrawDummyGraph(); } void MainWindow::GoodBye(){ for( int i = 0; i < nDigi; i++) digi[i]->CloseDigitizer(); for( int i = 0; i < nDigi; i++) delete digi[i]; for( int i = 0; i < MaxNBoards; i++){ delete hChannel[i]; for( int j = 0; j < MaxNChannels; j++){ delete hEnergy[i][j]; } } delete gDummy; delete gAnaTrace1 ; delete gAnaTrace2 ; delete gDigiTrace1; delete gDigiTrace2; printf("----- bye bye ---- \n"); gApplication->Terminate(0); } MainWindow::~MainWindow() { /// The destrcutor is overrided by GoodBye(); printf("----- %s \n", __func__); delete fMenuBar; delete fMenuFile; delete fMenuDigitizers; delete fMenuUtility; delete fEcanvas; delete boardIDEntry; delete chIDEntry; delete teLog; delete bOpenDigitizers; delete bStartRun; delete bStopRun; delete cbMode; delete dataPrefix; delete runIDEntry; delete cbDataRun; delete bPlotSingleTrace; delete bFitTrace; delete boardSetting; delete channelSettingPHA; delete channelSettingPSD; delete registerSetting; delete triggerSummary; delete programSetting; delete runThread; fMain->Cleanup(); delete fMain; } void MainWindow::HandleMenu(Int_t id){ switch(id){ ///========================= Scan digitizers case M_DIGITIZER_OPEN:{ OpenDigitizers(); }break; ///========================= File Open case M_FILE_OPEN:{ LogMsg((char *) "Not implemented."); }break; ///========================= Exit case M_EXIT: GoodBye(); break; ///========================= Trigger summary case M_TRIGGER_SUMMARY: { triggerSummary = new TriggerSummary(gClient->GetRoot(), 600, 600); }break; case M_LOAD_SETTINGS:{ LoadSettingFromFile(); }break; ///========================= Channel setting case M_CH_SETTING_PHA: channelSettingPHA = new ChannelSettingPHA(gClient->GetRoot(), 600, 600, 0); channelSettingPHA->Connect("LogMsg(char*)", "MainWindow", this, "LogMsg(char*)"); channelSettingPHA->Connect("SendPlotTraceCmd()", "MainWindow", this, "PlotSingleTrace()"); break; case M_CH_SETTING_PSD: channelSettingPSD = new ChannelSettingPSD(gClient->GetRoot(), 600, 600, 0); channelSettingPSD->Connect("LogMsg(char*)", "MainWindow", this, "LogMsg(char*)"); //channelSettingPSD->Connect("SendPlotTraceCmd()", "MainWindow", this, "PlotSingleTrace()"); break; ///========================= Board setting case M_BOARD_SETTINGS:{ boardSetting = new BoardSetting(gClient->GetRoot(), 600, 600); boardSetting->Connect("LogMsg(char*)", "MainWindow", this, "LogMsg(char*)"); boardSetting->Connect("Haha(Int_t)", "MainWindow", this, "OpenChannelSetting(Int_t)"); }break; ///========================= Setting Summary case M_REGISTER_SETTING:{ registerSetting = new RegisterSetting(gClient->GetRoot(), 600, 600, Register::DPP::RecordLength_G); ///registerSetting->Connect("SendChangeSignal()", "ChannelSettingPHA", this, "ChangeCh()"); ///registerSetting->Connect("SendChangeSignal()", "ChannelSettingPSD", this, "ChangeCh()"); }break; ///========================= Program setting case M_PROGRAM_SETTINGS:{ programSetting = new ProgramSetting(gClient->GetRoot()); programSetting->Connect("SetSetting()", "MainWindow", this, "UpdateExpName()"); ///LogMsg((char*) Form("database : %s, name : %s ", ProgramSetting::databaseIP.c_str(), ProgramSetting::databaseName.c_str() )); }break; ///====================== Fit Gaussian case M_FINDPEAKS:{ LogMsg((char*)"[Find Gaussian Peaks] Not impelmented"); }break; } } void MainWindow::OpenDigitizers(){ /// if dig exist, say, from loading setting file without digitizer for( int i = 0 ; i < nDigi; i++ ) delete digi[i]; nDigi = 0; LogMsg((char*)"============= detect digitizers"); std::vector DPPType; DPPType.clear(); portID.clear(); boardID.clear(); nDigi = 0; Digitizer * dig = new Digitizer(); LogMsg((char*)"Finding Digitizer for 4 ports and 3 boards for each port..."); for( int port = 0; port < 4 ; port ++){ for( int board = 0; board < 3 ; board ++){ dig->OpenDigitizer(board, port); if ( dig->GetConnectionStatus() ) { nDigi++; DPPType.push_back(dig->GetDPPType()); portID.push_back(port); boardID.push_back(board); serialNum.push_back(dig->GetSerialNumber()); dig->CloseDigitizer(); } } } delete dig; LogMsg(Form("========== found %d digitizer(s)", nDigi)); for( int i = 0 ; i < nDigi ; i++){ LogMsg(Form("port: %d, board: %d, DPP Type : %d", portID[i], boardID[i], DPPType[i])); } if( nDigi > 0 ) { LogMsg(Form("============= Connect %d digitizer(s)...", nDigi)); digi = new Digitizer * [nDigi]; for( int i = 0; i < nDigi; i++){ printf("------------ %d \n", i); digi[i] = new Digitizer(boardID[i], portID[i], false, false); LogMsg(Form("%2d, Serial number : %3d opened (%s, %s)", i, digi[i]->GetSerialNumber(), digi[i]->GetDPPString().c_str(), digi[i]->GetModelName().c_str())); digi[i]->OpenSettingBinary(ProgramSetting::DataSavingPath + "/settings/setting_" + std::to_string(digi[i]->GetSerialNumber()) + ".bin"); } fMenuDigitizers->DisableEntry( M_DIGITIZER_OPEN); fMenuDigitizers->DisableEntry( M_LOAD_SETTINGS); fMenuDigitizers->EnableEntry( M_BOARD_SETTINGS); fMenuDigitizers->EnableEntry( M_CH_SETTING_PHA); fMenuDigitizers->EnableEntry( M_CH_SETTING_PSD); fMenuDigitizers->EnableEntry( M_TRIGGER_SUMMARY); fMenuDigitizers->EnableEntry( M_REGISTER_SETTING); bOpenDigitizers->SetEnabled(false); bStartRun->SetEnabled(true); if( nDigi > 1) boardIDEntry->SetState(true); chIDEntry->SetState(true); boardIDEntry->SetLimits(TGNumberFormat::kNELLimitMinMax, 0, nDigi-1); boardIDEntry->SetNumber(0, false); chIDEntry->SetLimits(TGNumberFormat::kNELLimitMinMax, 0, digi[0]->GetNChannel() -1 ); bPlotSingleTrace->SetEnabled(true); bFitTrace->SetEnabled(true); for( int i = 0; i < nDigi; i++){ hChannel[i] = new TH1F(Form("hBd%02d", i),Form("hBd%02d; ch; count", i), digi[i]->GetNChannel(), 0, digi[i]->GetNChannel()); for( int j = 0; j < MaxNChannels; j++) hEnergy[i][j] = new TH1F(Form("hE%02dch%02d", i, j),Form("hE bd-%02d ch-%02d; Energy[ch]; count", i, j), 400, 0, 30000); } } } void MainWindow::LoadSettingFromFile(){ const char *filetypes[] = { "Setting File", "*.bin", "ROOT files", "*.root", "ROOT macros", "*.C", "Text files", "*.[tT][xX][tT]", 0, 0 }; TGFileInfo fi; fi.fFileTypes = filetypes; fi.SetIniDir("."); printf("fIniDir = %s\n", fi.fIniDir); new TGFileDialog(gClient->GetRoot(), fMain, kFDOpen, &fi); printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir); if( fi.fFilename == NULL) return; int loadStatus = -1; /// if no digitize open if( digi == NULL ) { LogMsg((char *)"No Digitizer is connected. Create a dummy digitizer."); digi = new Digitizer *[1]; nDigi = 1; digi[0] = new Digitizer(); loadStatus = digi[0]->LoadSettingBinary( fi.fFilename ); boardIDEntry->SetNumber(0, false); }else{ loadStatus = digi[0]->LoadSettingBinary( fi.fFilename ); /// still dummy digitizer } HandleMenu(M_BOARD_SETTINGS); OpenChannelSetting(0); } void MainWindow::ChangeBoard(){ int boardID = boardIDEntry->GetNumber(); chIDEntry->SetLimits(TGNumberFormat::kNELLimitMinMax, 0, digi[boardID]->GetNChannel() -1 ); ChangePlot(); } void MainWindow::UpdateExpName(){ dataPrefix->SetText(ProgramSetting::ExpName.c_str()); runIDEntry->SetNumber(lastRunID); } void MainWindow::MakeElogEntry(bool start){ if( ProgramSetting::EnableElog == false ) return; TString cmd = Form("%s/DAQ/elogEntry.sh %d", ProgramSetting::programPath.c_str(), start); int temp = system(cmd.Data()); } void MainWindow::StartRun(){ LogMsg(Form("%s",__func__)); if( digi == NULL) return; for( int bd = 0; bd < nDigi; bd++){ hChannel[bd]->Reset(); for( int ch = 0; ch < MaxNChannels; ch++){ hEnergy[bd][ch]->Reset(); } } bStartRun->SetEnabled(false); bStopRun->SetEnabled(true); dataPrefix->SetEnabled(false); runIDEntry->SetState(false); bPlotSingleTrace->SetEnabled(false); bFitTrace->SetEnabled(false); if( cbDataRun->GetState() == kButtonDown ) { cbMode->SetEnabled(false); MakeElogEntry(true); } HandleMenu(M_TRIGGER_SUMMARY); bool threadFlag = false; for( int i = 0 ; i < nDigi; i++) { digi[i]->StartACQ(); if( digi[i]->IsRunning() ) threadFlag = true; } if( threadFlag ) runThread->Run(); if( boardSetting != NULL ) boardSetting->ReadStatus(); } void MainWindow::StopRun(){ LogMsg(Form("%s",__func__)); if( digi == NULL) return; for( int i = 0; i < nDigi; i++) digi[i]->StopACQ(); runThread->Join(); ///===== clear data; for( int i = 0; i < nDigi; i++) digi[i]->GetData()->ClearTriggerRate(); bStartRun->SetEnabled(true); bStopRun->SetEnabled(false); dataPrefix->SetEnabled(true); runIDEntry->SetState(true); bPlotSingleTrace->SetEnabled(true); bFitTrace->SetEnabled(true); cbMode->SetEnabled(true); if( triggerSummary != NULL ) triggerSummary->CloseWindow(); ///if( cbMode->GetSelected() == Mode_DataRun ){ if( cbDataRun->GetState() == kButtonDown ) { int runID = runIDEntry->GetNumber(); lastRunID = runID + 1; runIDEntry->SetNumber(runID +1); MakeElogEntry(false); ProgramSetting::SaveProgramSetting(); } } void MainWindow::OpenChannelSetting(Int_t boardID){ if( digi == NULL ) return; if( digi[boardID]->GetDPPType() == V1730_DPP_PHA_CODE ){ channelSettingPHA = new ChannelSettingPHA(gClient->GetRoot(), 600, 600, boardID); channelSettingPHA->Connect("LogMsg(char*)", "MainWindow", this, "LogMsg(char*)"); channelSettingPHA->Connect("SendPlotTraceCmd()", "MainWindow", this, "PlotSingleTrace()"); } if( digi[boardID]->GetDPPType() == V1730_DPP_PSD_CODE ){ channelSettingPSD = new ChannelSettingPSD(gClient->GetRoot(), 600, 600, boardID); channelSettingPSD->Connect("LogMsg(char*)", "MainWindow", this, "LogMsg(char*)"); //channelSettingPSD->Connect("SendPlotTraceCmd()", "MainWindow", this, "PlotSingleTrace()"); } } //TODO, should merge into LogMsg. void MainWindow::UpdateChannelSetting(){ if( digi == NULL ) return; if( channelSettingPHA != NULL ) channelSettingPHA->ChangeCh(); if( channelSettingPSD != NULL ) channelSettingPSD->ChangeCh(); } void MainWindow::LogMsg(char * msg){ time_t now = time(0); tm * ltm = localtime(&now); int year = 1900 + ltm->tm_year; int month = 1 + ltm->tm_mon; int day = ltm->tm_mday; int hour = ltm->tm_hour; int minute = ltm->tm_min; int secound = ltm->tm_sec; TString outMsg = Form("[%4d-%02d-%02d %02d:%02d:%02d] %s", year, month, day, hour, minute, secound, msg); teLog->AddLine(outMsg); printf("%s\n", outMsg.Data()); teLog->ShowBottom(); } void MainWindow::DrawDummyGraph(){ int boardID = boardIDEntry->GetNumber(); int chID = chIDEntry->GetNumber(); int ch2ns = 4.0; uint32_t rl = 125; fEcanvas->GetCanvas()->cd(); if( digi != NULL ) { ch2ns = (int) digi[boardID]->GetCh2ns(); rl = digi[boardID]->GetSettingFromMemory(Register::DPP::RecordLength_G, chID); } gDummy->SetPoint(1, 8.*rl*ch2ns, 0); gDummy->SetLineColor(15); gDummy->Draw("AL"); gDummy->GetXaxis()->SetRangeUser(0, 8*rl*ch2ns); gDummy->GetYaxis()->SetRangeUser(-1000, 0x3FFF); } void MainWindow::PlotSingleTrace(){ printf("=== %s\n", __func__); if( digi == NULL ) return; int boardID = boardIDEntry->GetNumber(); int chID = chIDEntry->GetNumber(); uint32_t bdConfig = digi[boardID]->GetSettingFromMemory(Register::DPP::BoardConfiguration); bool isDualTrace = ( bdConfig >> 11 ) & 0x1; bool isRecordWave = ( bdConfig >> 16 ) & 0x1; if( !isRecordWave ) { LogMsg((char *) "Please enable trace recording."); return; } Data * data = digi[boardID]->GetData(); int ch2ns = (int) digi[boardID]->GetCh2ns(); DrawDummyGraph(); digi[boardID]->StartACQ(); int count = 0; while(count < 10){ usleep(100*1000); /// wait half sec digi[boardID]->ReadData(); if( data->nByte > 0 ){ data->DecodeBuffer(false, 2); data->PrintStat(); int traceLength = (data->Waveform1[chID][0]).size(); if( traceLength == 0 ) { LogMsg((char *)"no trace"); bFitTrace->SetEnabled(false); }else{ for( int i = 0; i < traceLength ; i++) { gAnaTrace1->SetPoint(i, i*ch2ns*(1+isDualTrace), (data->Waveform1[chID][0])[i]); } double xmin, xmax, ymin, ymax; gAnaTrace1->ComputeRange(xmin, ymin, xmax, ymax); for( int i = 0; i < traceLength ; i++) { gDigiTrace1->SetPoint(i, i*ch2ns*(1+isDualTrace), (ymax-ymin)*(data->DigiWaveform1[chID][0])[i] + ymin); if( isDualTrace) { short haha = (data->Waveform2[chID][0])[i]; if( haha > 0x1FFF ) haha -= 0x3FFF; gAnaTrace2->SetPoint(i, i*ch2ns*(1+isDualTrace), haha); } } } data->ClearData(); fEcanvas->GetCanvas()->cd(); gAnaTrace1->Draw("same L"); gAnaTrace2->Draw("same L"); gDigiTrace1->Draw("same L"); fEcanvas->GetCanvas()->Update(); break; bFitTrace->SetEnabled(true); } count++; }; digi[0]->StopACQ(); if( count == 10 ) LogMsg((char*)"Plot Trace TimeOut, please check setting"); } void MainWindow::FitTrace(){ printf("=== %s not impletement.\n", __func__); if( gAnaTrace1->GetN() == 0 ) return; double xmin, xmax, ymin, ymax; gAnaTrace1->ComputeRange(xmin, ymin, xmax, ymax); TF1 * f1 = new TF1("f1", traceFunc, xmin, xmax, 5); f1->SetLineWidth(3); f1->SetLineColor(1); f1->SetNpx(1000); f1->SetParameter(0, ymin); f1->SetParameter(1, 1000); //TODO get from digi[Board]->PreTrigger * 4 * ch2ns f1->SetParameter(2, 20); f1->SetParameter(3, ymax-ymin); f1->SetParameter(4, 50000); gAnaTrace1->Fit("f1", "R"); fEcanvas->GetCanvas()->Update(); gSystem->ProcessEvents(); const Double_t* paraE = f1->GetParErrors(); const Double_t* paraA = f1->GetParameters(); LogMsg((char*)"---------- Fit result"); } void MainWindow::ChangePlot(){ int boardID = boardIDEntry->GetNumber(); int ch = chIDEntry->GetNumber(); fEcanvas->GetCanvas()->cd(); if( cbMode->GetSelected() == Mode_CountHist ) hChannel[boardID]->Draw("hist"); if( cbMode->GetSelected() == Mode_EnergyHist ) hEnergy[boardID][ch]->Draw("hist"); if( cbMode->GetSelected() == Mode_Oscilloscope ){ DrawDummyGraph(); uint32_t bdConfig = digi[boardID]->GetSettingFromMemory(Register::DPP::BoardConfiguration); bool isDualTrace = ( bdConfig >> 11 ) & 0x1; gAnaTrace1->GetYaxis()->SetRangeUser(0, 0x3FFF); gAnaTrace1->Draw("L"); if( isDualTrace ) gAnaTrace2->Draw("L"); gDigiTrace1->Draw("L"); } fEcanvas->GetCanvas()->Update(); } //TODO use the ptr to tell which board, and each digitizer has an indivual thread for savign data and filling hists. void * MainWindow::Run(void * ptr){ printf("=== %s\n", __func__); if( digi == NULL ) return 0; int boardID = boardIDEntry->GetNumber(); int ch = 0; int ch2ns = 4; int traceLength = 0; uint32_t PreviousTime = get_time(); uint32_t CurrentTime = 0; uint32_t ElapsedTime = 0; TString dataFileName = ProgramSetting::DataSavingPath + "/data/" + dataPrefix->GetText(); dataFileName += Form("_run%03d", (int) runIDEntry->GetNumber()); printf("|%s|\n", dataFileName.Data()); if( cbDataRun->GetState() == kButtonDown) { TString msg = Form("Save data to : %s_***.bin\n", dataFileName.Data()); teLog->AddLine(msg.Data()); teLog->ShowBottom(); } uint32_t bdConfig = digi[boardID]->GetSettingFromMemory(Register::DPP::BoardConfiguration); bool isDualTrace = ( bdConfig >> 11 ) & 0x1; bool hasTrace = (bdConfig >> 16 ) & 0x1; Data * data = digi[boardID]->GetData(); DrawDummyGraph(); while(digi[boardID]->IsRunning()){ usleep(100*1000); /// wait 100 msec digi[boardID]->ReadData(); if( boardSetting != NULL ) boardSetting->ReadStatus(); ch2ns = (int) digi[boardID]->GetCh2ns(); ch = chIDEntry->GetNumber(); if( data->nByte > 0 ){ //data->PrintStat(); if( cbDataRun->GetState() == kButtonDown ) { // Rate graph? data->SaveBuffer(dataFileName.Data()); data->DecodeBuffer(true, 0); CurrentTime = get_time(); if( CurrentTime - PreviousTime > 1000 ){ std::string msg = Form("File Size : %.2f MB", data->GetPresentFileSize() / 1024./1024. ); teLog->AddLine(msg.c_str()); teLog->ShowBottom(); PreviousTime = CurrentTime; } }else{ data->DecodeBuffer(false, 0); } } if( cbDataRun->GetState() == kButtonUp ) { fEcanvas->GetCanvas()->cd(); /// use the last trace if( cbMode->GetSelected() == Mode_Oscilloscope && hasTrace){ unsigned short nData = data->NumEvents[ch]; traceLength = (data->Waveform1[ch][nData-1]).size(); if( traceLength > 0 ){ for( int i = 0; i < traceLength; i++) { gAnaTrace1->SetPoint(i, i*ch2ns*(1+isDualTrace), (data->Waveform1[ch][nData-1])[i]); if( isDualTrace) { short haha = (data->Waveform2[ch][nData-1])[i]; if( haha > 0x1FFF ) haha -= 0x3FFF; gAnaTrace2->SetPoint(i, i*ch2ns*(1+isDualTrace), haha ); } } /// since the gDummy fixed the draw range, it does not really matter to remove extra points gAnaTrace1->Draw("same L"); gAnaTrace2->Draw("same L"); } } CurrentTime = get_time(); ElapsedTime = CurrentTime - PreviousTime; /// milliseconds if( ElapsedTime > 200 ){ ///Fill Channel Count for( int i = 0 ; i < digi[boardID]->GetNChannel(); i++){ for( int j = 0; j < data->NumEvents[i]; j++) hChannel[boardID]->Fill(i); } ///Fill Energy histogram for( int i = 0; i < data->NumEvents[ch]; i++){ hEnergy[boardID][ch]->Fill( data->Energy[ch][i] ); } if( cbMode->GetSelected() == Mode_EnergyHist ) hEnergy[boardID][ch]->Draw("hist"); if( cbMode->GetSelected() == Mode_CountHist ) hChannel[boardID]->Draw("hist"); data->ClearData(); PreviousTime = CurrentTime; } fEcanvas->GetCanvas()->Update(); } data->ClearData(); } return ptr; } //############################################ int main(int argc, char **argv) { printf(" Welcome to FSU DQ \n"); ProgramSetting::LoadProgramSetting(); TApplication theApp("App",&argc,argv); new MainWindow(gClient->GetRoot(),800,800); theApp.Run(); printf("------ see you next time :) ------ \n"); return 0; }