FSUDAQ/DAQ/FSUDAQ.cpp

1008 lines
33 KiB
C++

#include <TApplication.h>
#include <TGClient.h>
#include <TSystem.h>
#include <TStyle.h>
#include <TCanvas.h>
#include <TF1.h>
#include <TRandom.h>
#include <TGButton.h>
#include <TRootEmbeddedCanvas.h>
#include <TGMenu.h>
#include <TGLabel.h>
#include <TGNumberEntry.h>
#include <TGraph.h>
#include <TAxis.h>
#include <TGFileDialog.h>
#include <TF1.h>
#include <TGMsgBox.h>
#include <unistd.h>
#include <ctime>
#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;
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();
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;
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<int> 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);
}
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);
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"));
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()");
}
}
//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->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");
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();
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");
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;
}