#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "FSUDAQ.h" 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; InfluxDB * influx = NULL; unsigned short nDigi = 0; Digitizer ** digi = NULL; unsigned short lastRunID; ///============ static members TGTextView * 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_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) { 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->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_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,0,0,0,0)); {///================= Create a horizontal frame widget with buttons TGGroupFrame * group0 = new TGGroupFrame(hframe, "Run Control", kVerticalFrame); hframe->AddFrame(group0, new TGLayoutHints(kLHintsExpandY)); 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 + 1, 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 TGTextView(groupLog, w, 100); groupLog->AddFrame(teLog, new TGLayoutHints(kLHintsExpandX, 2,2,10,0) ); teLog->SetReadOnly(true); } /// 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_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(); influx = new InfluxDB(ProgramSetting::databaseIP, false); fMain->Move(300, 200); } void MainWindow::GoodBye(){ printf("/// Closing Digitizer and Releasing digitizer memory\n"); for( int i = 0; i < nDigi; i++) delete digi[i]; for( int i = 0; i < MaxNBoards; i++){ if( hChannel[i] != NULL ) delete hChannel[i]; for( int j = 0; j < MaxNChannels; j++){ if( hEnergy[i][j] != NULL ) delete hEnergy[i][j]; } } delete gDummy; delete gAnaTrace1 ; delete gAnaTrace2 ; delete gDigiTrace1; delete gDigiTrace2; delete influx; 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 startStopDialog; // //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; ///========================= Load setting file offline 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()"); programSetting->Connect("LogMsg(char*)", "MainWindow", this, "LogMsg(char*)"); }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(); TString haha = Form("Finding Digitizer for %d ports and %d boards for each port...", ProgramSetting::maxPort, ProgramSetting::maxBoardPrePort ); LogMsg((char*) haha.Data()); for( int port = 0; port < ProgramSetting::maxPort ; port ++){ for( int board = 0; board < ProgramSetting::maxBoardPrePort ; 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++){ 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]->SetSettingBinaryPath(ProgramSetting::DataSavingPath + "/settings/setting_" + std::to_string(digi[i]->GetSerialNumber()) + ".bin"); ///The maxAggBLT is always 1 when open digitizer. uint32_t maxAggBLT = digi[i]->ReadSettingFromFile(Register::DPP::MaxAggregatePerBlockTransfer); digi[i]->WriteRegister(Register::DPP::MaxAggregatePerBlockTransfer, maxAggBLT); } 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_REGISTER_SETTING); bOpenDigitizers->SetEnabled(false); triggerSummary = new TriggerSummary(gClient->GetRoot(), fMain ); 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]->LoadSettingBinaryToMemory( fi.fFilename ); boardIDEntry->SetNumber(0, false); }else{ loadStatus = digi[0]->LoadSettingBinaryToMemory( fi.fFilename ); digi[0]->ProgramSettingsToBoard(); } 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 + 1); influx->SetURL(ProgramSetting::databaseIP); ///Check database exist influx->ShowDatabases(); std::vector list = influx->GetDatabaseList(); bool dataBaseExist = false; for( int i = 0; i < (int) list.size(); i++){ if( list[i] == ProgramSetting::databaseName ) { dataBaseExist = true; break; } } if( !dataBaseExist ) influx->CreateDatabase(ProgramSetting::databaseName); influx->ClearDataPointsBuffer(); influx->AddDataPoint("SavingData,ExpName=" + ProgramSetting::ExpName + " value=0"); influx->WriteData(ProgramSetting::databaseName); } void MainWindow::MakeElogEntry(bool start){ if( !ProgramSetting::EnableElog ) return; printf("==== Creating elog \n"); TString cmd = Form("%s/DAQ/elogEntry.sh %d \"%s\"", ProgramSetting::programPath.c_str(), start, StartStopDialog::Comment.Data()); int temp = system(cmd.Data()); } void MainWindow::StartRun(){ 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() == kButtonUp ) { bool threadFlag = false; for( int i = 0 ; i < nDigi; i++) { digi[i]->StartACQ(); if( digi[i]->IsRunning() ) threadFlag = true; } if( threadFlag ) runThread->Run(); }else{ startStopDialog = new StartStopDialog(gClient->GetRoot(), fMain, 400, 200, true); if( StartStopDialog::isOK){ LogMsg(Form("Start Data Run")); lastRunID ++; ProgramSetting::SaveProgramSetting(); cbMode->SetEnabled(false); MakeElogEntry(true); influx->ClearDataPointsBuffer(); influx->AddDataPoint("SavingData,ExpName=" + ProgramSetting::ExpName + " value=1"); influx->AddDataPoint("RunID value=" + std::to_string(lastRunID)); influx->PrintDataPoints(); influx->WriteData(ProgramSetting::databaseName); bool threadFlag = false; for( int i = 0 ; i < nDigi; i++) { digi[i]->StartACQ(); if( digi[i]->IsRunning() ) threadFlag = true; } if( threadFlag ) runThread->Run(); }else{ bStartRun->SetEnabled(true); bStopRun->SetEnabled(false); dataPrefix->SetEnabled(true); runIDEntry->SetState(true); bPlotSingleTrace->SetEnabled(true); bFitTrace->SetEnabled(true); cbMode->SetEnabled(true); } } } void MainWindow::StopRun(){ 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( cbMode->GetSelected() == Mode_DataRun ){ if( cbDataRun->GetState() == kButtonDown ) { startStopDialog = new StartStopDialog(gClient->GetRoot(), fMain, 400, 200, false); if( StartStopDialog::isOK){ LogMsg(Form("Stop Data Run")); influx->ClearDataPointsBuffer(); influx->AddDataPoint("SavingData,ExpName=" + ProgramSetting::ExpName + " value=0"); influx->WriteData(ProgramSetting::databaseName); int runID = runIDEntry->GetNumber(); runIDEntry->SetNumber(runID +1); MakeElogEntry(false); }else{ bStartRun->SetEnabled(false); bStopRun->SetEnabled(true); dataPrefix->SetEnabled(false); runIDEntry->SetState(false); bPlotSingleTrace->SetEnabled(false); bFitTrace->SetEnabled(false); } } } 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()"); } } 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->AddLineFast(outMsg); printf("%s\n", outMsg.Data()); teLog->Update(); 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; int traceLength; while(count < 10){ usleep(100*1000); /// wait half sec digi[boardID]->ReadData(); if( data->nByte > 0 ){ data->DecodeBuffer(false, 2); data->PrintStat(); 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"); if( isDualTrace) 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; uint32_t t1 = get_time(); uint32_t t2 = 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->AddLineFast(msg.Data()); teLog->Update(); 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(); unsigned int printFileSizeCount = 0; unsigned int nLine; while(digi[boardID]->IsRunning()){ usleep(100*1000); /// wait 100 msec digi[boardID]->ReadData(); ch2ns = (int) digi[boardID]->GetCh2ns(); ch = chIDEntry->GetNumber(); if( data->nByte > 0 ){ if( cbDataRun->GetState() == kButtonDown ) { data->SaveBuffer(dataFileName.Data()); data->DecodeBuffer(true, 0); CurrentTime = get_time(); if( CurrentTime - PreviousTime > 1e6 ){ //if( printFileSizeCount > 0 ){ // nLine = teLog->ReturnLineCount(); // teLog->GetText()->DelLine(nLine-1); //} //std::string msg = Form("File Size : %.2f MB", data->GetPresentFileSize() / 1024./1024. ); //teLog->AddLineFast(msg.c_str()); //teLog->Update(); //teLog->ShowBottom(); influx->ClearDataPointsBuffer(); influx->AddDataPoint("FileSize value=" + std::to_string(data->GetPresentFileSize())); influx->WriteData(ProgramSetting::databaseName); PreviousTime = CurrentTime; printFileSizeCount ++; } }else{ data->DecodeBuffer(false, 0); } //t2 = get_time(); //printf("========= dt : %u usec\n", t2 - t1); ////data->PrintStat(); //t1 = t2 ; } 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"); if( isDualTrace) gAnaTrace2->Draw("same L"); } } CurrentTime = get_time(); ElapsedTime = CurrentTime - PreviousTime; /// milliseconds if( ElapsedTime > 1000 * 1000 && BoardSetting::isOpened ) boardSetting->ReadStatus(); if( ElapsedTime > 200 * 1000 ){ ///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("########################################################################################\n"); printf(" oooooooooooo .oooooo..o ooooo ooo oooooooooo. .o. .oooooo. \n"); printf(" `888\' `8 d8P' `Y8 `888' `8' `888' `Y8b .888. d8P' `Y8b \n"); printf(" 888 Y88bo. 888 8 888 888 .8`888. 888 888 \n"); printf(" 888oooo8 ``Y8888o. 888 8 888 888 .8' `888. 888 888 \n"); printf(" 888 \" ``Y88b 888 8 888 888 .88ooo8888. 888 888 \n"); printf(" 888 oo .d8P `88. .8' 888 d88' .8' `888. `88b d88b \n"); printf(" o888o 8\"\"88888P' `YbodP' o888bood8P' o88o o8888o `Y8bood8P'Ybd' \n"); printf("########################################################################################\n"); printf(" Welcome to FSU DAQ \n"); ProgramSetting::LoadProgramSetting(); TApplication theApp("App",&argc,argv); new MainWindow(gClient->GetRoot(),800,800); theApp.Run(); return 0; }