diff --git a/Analysis/EventBuilder_raw b/Analysis/EventBuilder_raw new file mode 100755 index 0000000..cdb81db Binary files /dev/null and b/Analysis/EventBuilder_raw differ diff --git a/Analysis/TimSyncComp.C b/Analysis/TimSyncComp.C new file mode 100755 index 0000000..7cc4ed5 --- /dev/null +++ b/Analysis/TimSyncComp.C @@ -0,0 +1,128 @@ +#include +#include +#include "TFile.h" +void quicksort( Double_t* arr1, Int_t* arr2, int left, int right) +{ + auto i = left; + auto j = right; + auto tmp = arr1[0]; + auto pivot = arr1[(int)((left + right)/2)]; + + // Partition + while (i <= j) { + while (arr1[i] < pivot) + i++; + while (arr1[j] > pivot) + j--; + if (i <= j) { + // swap arr1 elements + tmp = arr1[i]; + arr1[i] = arr1[j]; + arr1[j] = tmp; + // swap arr2 elements + tmp = arr2[i]; + arr2[i] = arr2[j]; + arr2[j] = tmp; + i++; + j--; + } + }; + + // Recursion + if (left < j) + quicksort(arr1, arr2, left, j); + if (i < right) + quicksort(arr1, arr2, i, right); + + return; +} +void TimSyncComp() +{ + Char_t* f; TChain* MUSICdata = new TChain("Data_R"); + f ="/home/bavarians/exp/test0/DAQ/run/RAW/DataR_run.root"; + std::cout<Add(f); + double run_portion=0.01; + + //""""""""""""""""""""" + //TIME synchronization of the digital board + //""""""""""""""""""""" + // Double_t shiftTime[4] ={0.30026482, 0.200206944, 0.100003416, 0.0};//pulser + // Double_t shiftTime[4] ={0.192828788, 0.137373792 , 0.058816296, 0.0};//run28 + Double_t shiftTime[4] ={0, 0 ,0., 0.0}; + //""""""""""""""""""""" + //MAP + //""""""""""""""""""""" + //Left 0->15 + //Right 16->31 + //Individual{32=Grid, 33=S0, 34=cathode, 35=S17}, + //100=empty + int Map_DAQCha_to_MUSICStrip[4][16]={{34,100, 1, 100, 33, 100, 5, 100, 0, 100, 9, 100, 17, 13, 100, 32}, + {2, 100, 16, 100, 21, 100, 20, 100, 8, 100, 24, 100, 27, 28, 100, 14}, + {19, 100, 3, 100, 6, 100, 7, 100, 25, 100, 11, 100, 12, 15, 100, 31}, + {4, 100, 18, 36, 23, 100, 22, 100, 10, 100, 26, 100, 29, 30, 100, 35}}; + + + //""""""""""""""""""""" + //Data tree structure + //""""""""""""""""""""" + MUSICdata->SetBranchStatus("*", 0); + + UShort_t Channel; + ULong64_t Timestamp; + UShort_t Board; + UShort_t Energy; + + MUSICdata->SetBranchStatus("Channel", 1);MUSICdata->SetBranchAddress("Channel", &Channel); + MUSICdata->SetBranchStatus("Timestamp", 1);MUSICdata->SetBranchAddress("Timestamp", &Timestamp); + MUSICdata->SetBranchStatus("Board", 1);MUSICdata->SetBranchAddress("Board", &Board); + MUSICdata->SetBranchStatus("Energy", 1);MUSICdata->SetBranchAddress("Energy", &Energy); + + + double Ibeam = 30000.; + int nStat = MUSICdata->GetEntries(); + std::cout<LR16)",5000, 0,0+0.5,80,0,80); + Double_t* timestampVec = new Double_t[nStat]; Int_t* entryVec = new Int_t[nStat]; + for(int j=0;jGetEntry(j); + ChTimeBefore->Fill((Timestamp*1e-12)*1000. , Board*16+Channel); + timestampVec[j]= (Timestamp - shiftTime[Board]*1e+12); + entryVec[j]=j; + } + quicksort(timestampVec, entryVec,0,nStat-1); + std::cout<<"sorted "<=0){ + PositiveTime=j; + break; + } + } + + //""""""""""""""""""""" + //checking synchronization + //""""""""""""""""""""" + Double_t TimeEv = timestampVec[PositiveTime]*1e-12; + + //""""""""""""""""""""" + //Plot definition + //""""""""""""""""""""" + TH2F* ChTimeAfter = new TH2F("ChTimeAfter", ";time(ms);channel(S0->LR16)",5000, 0, 0+0.5,80,0,80); + + for(int i=0;iGetEntry(entryVec[i]); + ChTimeAfter->Fill((timestampVec[i]*1e-12)*1e+3, Board*16+Channel); + } + TCanvas* c= new TCanvas("c","c",800,800);c->Divide(1,2); + gStyle->SetPalette(kThermometer); + c->cd(1);ChTimeBefore->Draw("colz"); +c->cd(2);ChTimeAfter->Draw("colz"); + +} diff --git a/Analysis/TimeSync.C b/Analysis/TimeSync.C new file mode 100755 index 0000000..16f23da --- /dev/null +++ b/Analysis/TimeSync.C @@ -0,0 +1,138 @@ +#include +#include +#include "TFile.h" +void quicksort( Double_t* arr1, Int_t* arr2, int left, int right) +{ + auto i = left; + auto j = right; + auto tmp = arr1[0]; + auto pivot = arr1[(int)((left + right)/2)]; + + // Partition + while (i <= j) { + while (arr1[i] < pivot) + i++; + while (arr1[j] > pivot) + j--; + if (i <= j) { + // swap arr1 elements + tmp = arr1[i]; + arr1[i] = arr1[j]; + arr1[j] = tmp; + // swap arr2 elements + tmp = arr2[i]; + arr2[i] = arr2[j]; + arr2[j] = tmp; + i++; + j--; + } + }; + + // Recursion + if (left < j) + quicksort(arr1, arr2, left, j); + if (i < right) + quicksort(arr1, arr2, i, right); + + return; +} +void TimeSync() +{ + Char_t* f; TChain* MUSICdata = new TChain("tree"); + f ="/fs2data/bavarians/MUSIC_Devel/FSUDAQ/Run_001_B0.root"; + std::cout<Add(f); + f ="/fs2data/bavarians/MUSIC_Devel/FSUDAQ/Run_001_B1.root"; + std::cout<Add(f); + f ="/fs2data/bavarians/MUSIC_Devel/FSUDAQ/Run_001_B2.root"; + std::cout<Add(f); + f ="/fs2data/bavarians/MUSIC_Devel/FSUDAQ/Run_001_B3.root"; + std::cout<Add(f); + double run_portion=0.01; + + //""""""""""""""""""""" + //TIME synchronization of the digital board + //""""""""""""""""""""" + + Double_t shiftTime[4] ={0.0, 0.0 , 0.0, 0.0}; + //""""""""""""""""""""" + //MAP + //""""""""""""""""""""" + //Left 0->15 + //Right 16->31 + //Individual{32=Grid, 33=S0, 34=cathode, 35=S17, 40-43 pulser}, + //100=empty + int Map_DAQCha_to_MUSICStrip[4][16]={{34,100, 1, 100, 33, 40, 5, 100, 0, 100, 9, 100, 17, 13, 100, 32}, + {2, 100, 16, 100, 21, 41, 20, 100, 8, 100, 24, 100, 27, 28, 100, 14}, + {19, 100, 3, 100, 6, 42, 7, 100, 25, 100, 11, 100, 12, 15, 100, 31}, + {4, 100, 18, 36, 23, 43, 22, 100, 10, 100, 26, 100, 29, 30, 100, 35}}; + + + //""""""""""""""""""""" + //Data tree structure + //""""""""""""""""""""" + MUSICdata->SetBranchStatus("*", 0); + + int MAX_MULTI =100; + + + unsigned short bd[MAX_MULTI] ; + unsigned short ch[MAX_MULTI] ; + unsigned long long e_t[MAX_MULTI] ; + + + MUSICdata->SetBranchStatus("ch", 1);MUSICdata->SetBranchAddress("ch", &ch); + MUSICdata->SetBranchStatus("bd", 1);MUSICdata->SetBranchAddress("bd", &bd); + MUSICdata->SetBranchStatus("e_t", 1);MUSICdata->SetBranchAddress("e_t", &e_t); + + + double Ibeam = 30000.; + int nStat = MUSICdata->GetEntries(); + std::cout<LR16)",5000, 1000,1000+1,80,0,80); + Double_t* timestampVec = new Double_t[nStat]; Int_t* entryVec = new Int_t[nStat]; + for(int j=0;jGetEntry(j); + ChTimeBefore->Fill((e_t[0]*1e-9)*1e+4 , bd[0]*16+ch[0]); + timestampVec[j]= (e_t[0] - shiftTime[bd[0]]*1e+9); + entryVec[j]=j; + } + quicksort(timestampVec, entryVec,0,nStat-1); + std::cout<<"sorted "<=0){ + PositiveTime=j; + break; + } + } + + //""""""""""""""""""""" + //checking synchronization + //""""""""""""""""""""" + Double_t TimeEv = timestampVec[PositiveTime]*1e-9; + + //""""""""""""""""""""" + //Plot definition + //""""""""""""""""""""" + TH2F* ChTimeAfter = new TH2F("ChTimeAfter", ";time(0.1 ms);channel(S0->LR16)",5000, 1000, 1000+1,80,0,80); + + for(int i=0;iGetEntry(entryVec[i]); + ChTimeAfter->Fill((timestampVec[i]*1e-9)*1e+4, bd[0]*16+ch[0]); + } + TCanvas* c= new TCanvas("c","c",800,800);c->Divide(1,2); + gStyle->SetPalette(kThermometer); + c->cd(1);ChTimeBefore->Draw("colz"); +c->cd(2);ChTimeAfter->Draw("colz"); + +} diff --git a/Analysis/timeshift.C b/Analysis/timeshift.C new file mode 100644 index 0000000..c7c6c90 --- /dev/null +++ b/Analysis/timeshift.C @@ -0,0 +1,302 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +TCanvas* cGraphs; +TCanvas* cProb; + + +void computeNSD2(TGraph* ref, TGraph* gr, + Double_t threshDT/*microsec*/, + Double_t OverlapTMin/*sec*/, + Double_t OverlapTMax/*sec*/, + Int_t& npts, + Double_t& NSD2) +{ + NSD2 = 0; + npts = 0; + for (Long64_t p=0; pGetN(); p++) { + Double_t tref, dtref, dt; + ref->GetPoint(p, tref, dtref); + if (tref>=OverlapTMin && tref<=OverlapTMax && dtref>threshDT) { + dt = gr->Eval(tref); + // cout << i << " (" << tref << "," << yref << "," << y << ")" << endl; + NSD2 += pow(dt-dtref,2); + npts++; + } + } + if (NSD2>0) { + NSD2 = sqrt(NSD2); + NSD2 /= npts; + } + else + NSD2 = 1.0; + return; +} + + + + + +Double_t findshift(TGraph* ref, TGraph* gr, + Double_t OverlapTMin/*sec*/, + Double_t OverlapTMax/*sec*/, + Double_t threshDT/*microsec*/) +{ + Double_t shift = 0; + Int_t iterations = 0; + TGraph* grShifted = (TGraph*)gr->Clone("grShifted"); + TRandom3 rdm; + Int_t npts = 0; + Double_t NSD2 = 0; // normalized sum of differences squared (NSD2) + Double_t prevNSD2 = 0; + Double_t NSD2min = 1; + Double_t tmin, tmax, aux; + Double_t tini; + TGraph* gInvNSD2 = new TGraph(); + + ref->GetPoint(0, tini, aux); + + // First get a coarse distribution of the 1/NSD2 + for (Int_t p=0; pGetN(); p++) { + npts = 0; + NSD2 = 0; + gr->GetPoint(p, shift, aux); + shift -= tini; + + // shift the graph time + for (Long64_t ps=0; psGetN(); ps++) { + Double_t tsec, dt; + gr->GetPoint(ps, tsec, dt); + grShifted->SetPoint(ps, tsec-shift, dt); + } + + // check that the min/max times are within the overlap limits + grShifted->GetPoint(0, tmin, aux); + grShifted->GetPoint(grShifted->GetN()-1, tmax, aux); + if (tminOverlapTMax) { + // compute NSD2 of grShifted with respect to ref + computeNSD2(ref, grShifted, threshDT, OverlapTMin, OverlapTMax, npts, NSD2); + // cout << p << " "; + // cout.precision(10); + // cout << shift; + // cout << " " << npts << " " << NSD2 << endl; + // Fill histogram with inverse NSD2 whose GetRandom() method + // will serve guide the search for a precise time shift. + gInvNSD2->SetPoint(gInvNSD2->GetN(), shift, 1/NSD2); + } + // cout << shift << " " << tmin1 << " " << tmax1 << "\n" << npts << " " << NSD2 << endl; + } + + // Retreive time shift with largest 1/NSD2 + Double_t bestshift = 0; // return value + Double_t maxInvNSD2 = 0; + Double_t invNSD2 = 0; + for (Int_t i=0; iGetN(); i++) { + gInvNSD2->GetPoint(i, shift, invNSD2); + if (invNSD2>maxInvNSD2) { + bestshift = shift; + maxInvNSD2 = invNSD2; + } + } + + cProb = new TCanvas("cPorb","Prob"); + gInvNSD2->Draw("al*"); + + return bestshift; +} + + + +//////////////////////////////////////////////////////////////////////////////// +// _______ _ _ _ __ _ // +// |__ __(_) | | (_)/ _| | // +// | | _ _ __ ___ ___ ___| |__ _| |_| |_ // +// | | | | '_ ` _ \ / _ \/ __| '_ \| | _| __| // +// | | | | | | | | | __/\__ \ | | | | | | |_ // +// |_| |_|_| |_| |_|\___||___/_| |_|_|_| \__| // +// // +// Main function of this code. +//////////////////////////////////////////////////////////////////////////////// + +int timeshift( + UShort_t Board=0, UShort_t Chan=5, + UShort_t minE=400, UShort_t maxE=600, +// UShort_t minE= 1800, UShort_t maxE=2300, + // UShort_t Board=1, UShort_t Chan=4, + // UShort_t minE= 1700, UShort_t maxE=2200, + // UShort_t Board=2, UShort_t Chan=4, + // UShort_t minE= 1500, UShort_t maxE=1900, + UShort_t refBoard=3, UShort_t refChan=5, + UShort_t refMinE= 400, UShort_t refMaxE=600, + Double_t OverlapTMin= 0.3/*sec*/, + Double_t OverlapTMax= 10,/*sec*/// + Double_t threshDT= 100/*microsec*/, //80 + Int_t MaxEntry=5000000, Int_t FindShift=1) +{ + + + TString infile = "/home/bavarians/exp/test0/DAQ/run/RAW/DataR_run.root"; + + TFile* myFile = new TFile(infile); + TTree* tree = (TTree*)myFile->Get("Data_R"); + tree->Print(); + + // Simple progress monitor + TStopwatch StpWatch; + Long64_t numEntries = tree->GetEntries();; + long double Frac[6]; + int fIndex = 0; + Frac[0] = 0.01; + Frac[1] = 0.25; + Frac[2] = 0.5; + Frac[3] = 0.75; + Frac[4] = 0.9; + Frac[5] = 1.0; + + + TTreeReader theReader("Data_R", myFile); + TTreeReaderValue rvTimestamp(theReader, "Timestamp"); + TTreeReaderValue rvBoard = {theReader, "Board"}; + TTreeReaderValue rvChannel = {theReader, "Channel"}; + TTreeReaderValue rvEnergy = {theReader, "Energy"}; + TTreeReaderValue rvFlags = {theReader, "Flags"}; + + + Long64_t nentries = theReader.GetEntries(); + + ULong64_t* ts0 = new ULong64_t[nentries]; // reference channel + ULong64_t* ts1 = new ULong64_t[nentries]; + + cout << "Extracting data from " << infile << " ..." << endl; + + Long64_t entry = 0; + Long64_t e0 = 0; + Long64_t e1 = 0; + + + // Save the timestamps in arrays for selected channels using beam related events (energy cut) + while(theReader.Next() && entryrefMinE && *rvEnergyminE && *rvEnergySetLineColor(kRed); + TGraph* Delta1 = new TGraph(); + Delta1->SetLineColor(kBlue); + + + Double_t MaxDeltaT = 0; + for (Long64_t i=0; ithreshDT) { + Delta0->SetPoint(Delta0->GetN(), ts0[i]/1e12/*sec*/, DTus); + if (DTus>MaxDeltaT) + MaxDeltaT = DTus; + } + } + + for (Long64_t i=0; ithreshDT) { + Delta1->SetPoint(Delta1->GetN(), ts1[i]/1e12-tshift, DTus); + if (DTus>MaxDeltaT) + MaxDeltaT = DTus; + } + } + + + Double_t tref, yref, y; + Double_t NSD2 = 0; // normalized sum of differences squared (NSD2) + Double_t NSD2min = 1; + Double_t tmin0, tmax0, tmin1, tmax1, tmin2, tmax2; + tmin0 = ts0[0]/1e12; + tmax0 = ts0[e0-1]/1e12; + tmin1 = ts1[0]/1e12; + tmax1 = ts1[e1-1]/1e12; + + if (tmin0<=OverlapTMin && tmax0>=OverlapTMax && tmin1<=OverlapTMin && tmax1>=OverlapTMax) { + if (FindShift) { + cout << "executing findshift() ..." << endl; + tshift = findshift(Delta0, Delta1, + OverlapTMin, OverlapTMax, threshDT); + cout.precision(10); + cout << "best timeshift: " << tshift << " sec" << endl; + } + else { + // Just compute the + Int_t npts = 0; + computeNSD2(Delta0, Delta1, threshDT, OverlapTMin, OverlapTMax, npts, NSD2); + cout << tshift << " " << npts << " " << NSD2 << endl; + } + } + else + cout << "Need more entries for channel 0 or 2" << endl; + + + // Draw the graphs + cGraphs = new TCanvas("cGraphs","graphs"); + TH2F* hbk = new TH2F("hbk","",10000,OverlapTMin, OverlapTMax, 20,0,1.2*MaxDeltaT); + hbk->GetXaxis()->SetTitle("Time [s]"); + hbk->GetXaxis()->CenterTitle(); + hbk->GetYaxis()->SetTitle("#DeltaT [#mus]"); + hbk->GetYaxis()->CenterTitle(); + TH2F* hba; + if (FindShift) { + cGraphs->Divide(1,2); + hbk->SetTitle("Before"); + hba = new TH2F("hba","After",10000,OverlapTMin, OverlapTMax, 20,0,1.2*MaxDeltaT); + hba->GetXaxis()->SetTitle("Time [s]"); + hba->GetXaxis()->CenterTitle(); + hba->GetYaxis()->SetTitle("#DeltaT [#mus]"); + hba->GetYaxis()->CenterTitle(); + cGraphs->cd(1); + hbk->Draw(); + Delta0->Draw("lp same"); + TGraph* Delta1clone = (TGraph*)Delta1->Clone();Delta1clone->Draw("lp same"); + + cGraphs->cd(2); + hba->Draw(); + Delta0->Draw("lp same"); + for (Int_t i=0; iGetN(); i++) { + Double_t tsec, DTus; + Delta1->GetPoint(i, tsec, DTus); + Delta1->SetPoint(i, tsec-tshift, DTus); + } + Delta1->Draw("lp same"); + } + else { + hbk->Draw(); + Delta0->Draw("lp same"); + Delta1->Draw("lp same"); + } + + + return 0; +} diff --git a/DAQ/Acquisition.cpp b/DAQ/Acquisition.cpp new file mode 100644 index 0000000..2660cdc --- /dev/null +++ b/DAQ/Acquisition.cpp @@ -0,0 +1,295 @@ +#include "macro.h" +#include "ClassData.h" +#include "ClassDigitizer.h" +#include "influxdb.h" +#include +#include +#include /** struct timeval, select() */ +#include /** tcgetattr(), tcsetattr() */ +#include +#include +#include "TString.h" +#include "TSystem.h" +#include +#include +#define nDig 4 +Digitizer * dig[4]; +std::mutex mtx[nDig]; +std::condition_variable cv; +bool ready = false; +bool stop_acquisition = false; + +timespec ts[nDig]; +static struct termios g_old_kbd_mode; +char* path_to_run="/home/bavarians/FSUDAQ_MUSIC/Run/"; +char* path_to_DAQ="/home/bavarians/FSUDAQ_MUSIC/"; + +static void cooked(void){ + tcsetattr(0, TCSANOW, &g_old_kbd_mode); +} + +static void uncooked(void){ + struct termios new_kbd_mode; + /** put keyboard (stdin, actually) in raw, unbuffered mode */ + tcgetattr(0, &g_old_kbd_mode); + memcpy(&new_kbd_mode, &g_old_kbd_mode, sizeof(struct termios)); + new_kbd_mode.c_lflag &= ~(ICANON | ECHO); + new_kbd_mode.c_cc[VTIME] = 0; + new_kbd_mode.c_cc[VMIN] = 1; + tcsetattr(0, TCSANOW, &new_kbd_mode); +} + +static void raw(void){ + + static char init; + if(init) return; + /** put keyboard (stdin, actually) in raw, unbuffered mode */ + uncooked(); + /** when we exit, go back to normal, "cooked" mode */ + atexit(cooked); + + init = 1; +} + +int keyboardhit(){ + + struct timeval timeout; + fd_set read_handles; + int status; + + raw(); + /** check stdin (fd 0) for activity */ + FD_ZERO(&read_handles); + FD_SET(0, &read_handles); + timeout.tv_sec = timeout.tv_usec = 0; + status = select(0 + 1, &read_handles, NULL, NULL, &timeout); + if(status < 0){ + printf("select() failed in keyboardhit()\n"); + exit(1); + } + return (status); +} + +int getch(void){ + unsigned char temp; + raw(); + /** stdin = fd 0 */ + if(read(0, &temp, 1) != 1) return 0; + return temp; +} + +void go() { + ready = true; + cv.notify_all(); +} + +void func(Digitizer * dig, double RunTime, int Rid, int Bid){ + std::unique_lock lck(mtx[Bid]); + while (!ready ){ + printf("waiting for unlock %d\n", Bid); + cv.wait(lck); + } + cv.notify_all(); + clock_gettime(CLOCK_REALTIME, &ts[Bid]); + printf("----thread %d ready. %ld ns\n", Bid, ts[Bid].tv_nsec); + + dig->StartACQ(); + if(RunTime>0){ + unsigned long time; + unsigned long time0 = get_time(); + do{ + usleep(5*1000); + dig->ReadData(); + dig->GetData()->DecodeBuffer(true,0); + //dig->GetData()->PrintStat(); + //dig->GetData()->PrintData(); + gSystem->cd(path_to_run); + dig->GetData()->SaveBuffer(Form("Run_%03u_B%01u",Rid, Bid)); + time = get_time(); + //printf("********************* time : %lu usec\n", time-time0); + } + while((time-time0)*1e-6<=(RunTime)); + time = get_time(); + //printf("********************* end time : %lu usec\n", time-time0); + dig->StopACQ(); + } + if(RunTime<=0){ + do{ + usleep(5*1000); + dig->ReadData(); + unsigned long time1 = get_time(); + dig->GetData()->DecodeBuffer(true,0); + unsigned long time2 = get_time(); + //dig->GetData()->PrintStat(); + //dig->GetData()->PrintData(); + gSystem->cd(path_to_run); + dig->GetData()->SaveBuffer(Form("Run_%03u_B%01u",Rid, Bid)); + } + while(RunTime<=0 && !stop_acquisition); + dig->StopACQ(); + } + printf("thread %d finished.\n", Bid); +} + +void boardSetParameters(int BI, Digitizer * dig, double BoardConfigurationval, double DPPAlgoCtrl, double DPPAlgoCtrl_10A0,double DPPAlgoCtrl_10AC, double ShapedTriggerWidthVal, double InputSec[7], double DiscriSec[4], double TrapSec[7]){ + //ALL channels + //GENERAL + dig->WriteRegister(Register::DPP::BoardConfiguration, BoardConfigurationval); //Reg=0x8000 + dig->WriteRegister(Register::DPP::DPPAlgorithmControl, DPPAlgoCtrl);//Reg=0x1080 + dig->WriteRegister(Register::DPP::PHA::DPPAlgorithmControl2_G, DPPAlgoCtrl_10A0); //Reg=0x10A0 + dig->WriteRegister(Register::DPP::PHA::DPPAlgorithmControl22_G, DPPAlgoCtrl_10AC); //Reg=0x10AC + //Input Section + dig->WriteRegister(Register::DPP::RecordLength_G, InputSec[1]); //Reg=0x1020 + //Syncrhonization Section + //Trigger/Veto/coinc Section + dig->WriteRegister(Register::DPP::PHA::ShapedTriggerWidth, ShapedTriggerWidthVal); //Reg=0x1084 + //Miscellaneaous Section + //per channel + for(int i=0;i<16;i++){ + //GENERAL + //Input Section + dig->WriteRegister(Register::DPP::PreTrigger, InputSec[2], i);//Reg=0x1038 + dig->WriteRegister(Register::DPP::ChannelDCOffset, InputSec[5], i);//Reg=0x1098 + dig->WriteRegister(Register::DPP::InputDynamicRange, InputSec[6], i);//Reg=0x1028 + //Discriminator Section + dig->WriteRegister(Register::DPP::PHA::TriggerThreshold,DiscriSec[0], i);//Reg=0x106C + dig->WriteRegister(Register::DPP::PHA::TriggerHoldOffWidth, DiscriSec[1], i);//Reg=0x1074 + dig->WriteRegister(Register::DPP::PHA::RCCR2SmoothingFactor,DiscriSec[2], i);//Reg=0x1054 + dig->WriteRegister(Register::DPP::PHA::InputRiseTime, DiscriSec[3], i);//Reg=0x1058 + //Trapezoid Section + dig->WriteRegister(Register::DPP::PHA::TrapezoidRiseTime,TrapSec[0], i);//Reg=0x105C + dig->WriteRegister(Register::DPP::PHA::TrapezoidFlatTop, TrapSec[1], i);//Reg=0x1060 + dig->WriteRegister(Register::DPP::PHA::DecayTime, TrapSec[2], i);//Reg=0x1068 + dig->WriteRegister(Register::DPP::PHA::PeakingTime,TrapSec[3], i);//Reg=0x1064 + dig->WriteRegister(Register::DPP::PHA::PeakHoldOff,TrapSec[5], i);//Reg=0x1078 + dig->WriteRegister(Register::DPP::PHA::FineGain,TrapSec[6], i);//Reg=0x10C4 + } + } + +void boardCommonParameters(Digitizer * dig){ + //all channels + dig->WriteRegister(Register::DPP::TriggerValidationMask_G , 0x00000000);//Reg=0x8100 + //per channels + for(int i=0;i<16;i++){ + dig->WriteRegister(Register::DPP::PHA::RiseTimeValidationWindow, 0x00000000, i);//Reg=0x1070 + dig->WriteRegister(Register::DPP::VetoWidth, 0x0000000A, i);//Reg=0x10D4 + dig->WriteRegister(Register::DPP::Scratch, 0xAAAAAAAA, i);//Reg=0xEF20 + dig->WriteRegister(Register::DPP::InterruptEventNumber, 0x00000000,i);//Reg=0xEF18 + dig->WriteRegister(Register::DPP::InterruptStatusID, 0x000000DD,i);//Reg=0xEF14 + dig->WriteRegister(Register::DPP::RelocationAddress, 0x00000000,i);//Reg=0xEF10 + dig->WriteRegister(Register::DPP::MCSTBaseAddressAndControl , 0x000000AA, i);//Reg=0xEF0C + dig->WriteRegister(Register::DPP::ReadoutControl, 0x00000010, i);//Reg=0xEF00 + dig->WriteRegister(Register::DPP::ExtendedVetoDelay, 0x12340014,i);//Reg=0x81C4 + dig->WriteRegister(Register::DPP::BufferOccupancyGain , 0x00000000, i);//Reg=0x81B4 + dig->WriteRegister(Register::DPP::FrontPanelLVDSIONewFeatures , 0x00001111, i);//Reg=0x81A0 + dig->WriteRegister(Register::DPP::RunStartStopDelay , 0x00000000, i);//Reg=0x8170 + dig->WriteRegister(Register::DPP::DisableExternalTrigger, 0x00000000,i);//Reg=0x817C + dig->WriteRegister(Register::DPP::FanSpeedControl, 0x00000020, i);//Reg=0x8168 + dig->WriteRegister(Register::MemoryBufferAlmostFullLevel, 0x00000000, i);//Reg=0x816C + dig->WriteRegister(Register::DPP::AcquisitionControl, 00000000,i);//Reg=0x8100 + dig->WriteRegister(Register::DPP::GlobalTriggerMask, 0x80000000,i);//Reg=0x810C + dig->WriteRegister(Register::DPP::FrontPanelTRGOUTEnableMask, 0x00000000, i);//Reg=0x8110 + dig->WriteRegister(Register::DPP::LVDSIOData, 0x0000FFFF, i);//Reg=0x8118 + dig->WriteRegister(Register::DPP::FrontPanelIOControl, 0x00008100, i);//Reg=0x811C + dig->WriteRegister(Register::DPP::ChannelEnableMask, 0x0000FFFF, i);//Reg=0x8120 + dig->WriteRegister(Register::DPP::VoltageLevelModeConfig, 0x00000000, i);//Reg=0x8138 + dig->WriteRegister(Register::DPP::AnalogMonitorMode, 0x00000000, i);//Reg=0x8144 + } + } + +int main(int argc, char* argv[]){ + + printf("=====================================\n"); + printf("=== FSU DAQ ===\n"); + printf("=====================================\n"); + if (argc < 2) { + printf("Incorrect number of arguments:\n"); + printf("%s [RunTime] [RunId] \n", argv[0]); + printf(" RunTime in sec, default = -1 if unstoppped \n"); + return 1; + } + double RunTime = atoi(argv[1]); + int Rid= atoi(argv[2]); + + //"""""""""""""""""""""""""""""" + //Opening digitizers + //"""""""""""""""""""""""""""""" + for(int d=0;dProgramPHABoard(); + dig[i]->ReadAllSettingsFromBoard(); + dig[i]->WriteRegister(Register::DPP::SoftwareClear_W, 1); + dig[i]->WriteRegister(Register::DPP::MaxAggregatePerBlockTransfer, 40);//80 Reg=0xEF1C + dig[i]->WriteRegister(Register::DPP::NumberEventsPerAggregate_G, 511);//1023-->forced in WriteRegisterFromFile Reg=0x1034 + printf("========== %d \n", dig[i]->ReadSettingFromFile(Register::DPP::MaxAggregatePerBlockTransfer)); + boardSetParameters(i, dig[i], BoardConfigurationval[i],DPPAlgoCtrl[i], DPPAlgoCtrl_10A0[i],DPPAlgoCtrl_10AC[i], ShapedTriggerWidthVal, InputSec[i], DiscriSec[i], TrapSec[i] ); + boardCommonParameters(dig[i]); + dig[i]-> SaveAllSettingsAsText(Form("reg_Board%i.txt",i)); + dig[i]->GetData()->SetSaveWaveToMemory(false); + } + + //"""""""""""""""""""""""""""""" + //Parallel digitizer data taking + //"""""""""""""""""""""""""""""" + std::thread fdig[nDig]; + for (int i = 0; i < nDig; ++i){ + fdig[i] = std::thread(func, dig[i],RunTime , Rid, i); + } + printf("%d threads ready to race...\n", nDig); + usleep(1000*1000); + if(RunTime<=0){ + printf("Enter to stop ..\n"); + if(getchar()){stop_acquisition=true;} + } + go(); + for (auto& f : fdig) f.join(); + printf("=========== finsihed.\n"); + long avg = 0; + for( int i =0; i < nDig ; i++) avg += ts[i].tv_nsec; + avg = avg/nDig; + long min , max; + for( int i =0; i < nDig; i++) { + if( i == 0 ){ + min = ts[i].tv_nsec; + max = ts[i].tv_nsec; + continue; + } + if( min > ts[i].tv_nsec) min = ts[i].tv_nsec; + if( max < ts[i].tv_nsec) max = ts[i].tv_nsec; + } + printf(" avg : %ld\n", avg); + printf(" min : %ld, %ld\n", min, avg - min); + printf(" max : %ld, %ld\n", max, max - avg); + printf(" diff : %ld\n", max-min); + for(int i=0;i (unsigned int)MaxSaveFileSize ) { /// 2 GB + if( inFileSize > (unsigned int)MaxSaveFileSize ) { /// 1 GB fclose(haha); saveFileIndex ++; sprintf(saveFileName, "%s_%03u.fsu", fileName , saveFileIndex); @@ -212,7 +213,7 @@ inline void Data::PrintBuffer() const{ inline void Data::PrintData() const{ printf("============================= Print Data\n"); for( int ch = 0; ch < MaxNChannels ; ch++){ - if( NumEvents[ch] == 0 ) continue; + if(NumEvents[ch] == 0 ) continue; printf("------------ ch : %d, %d \n", ch, NumEvents[ch]); for( int ev = 0; ev < NumEvents[ch] ; ev++){ printf("%4d, %5u, %15llu, %5u \n", ev, Energy[ch][ev], Timestamp[ch][ev], fineTime[ch][ev]); @@ -277,7 +278,6 @@ inline void Data::DecodeBuffer(bool fastDecode, int verbose){ nw = nw + 1; unsigned int bdAggCounter = ReadBuffer(nw, verbose); if( verbose >= 1 ) printf("Board Agg Counter : %u \n", bdAggCounter & 0x7FFFFF); - nw = nw + 1; unsigned int bdAggTimeTag = ReadBuffer(nw, verbose); if( verbose >= 2 ) printf("Agg Counter : %u \n", bdAggTimeTag); @@ -285,7 +285,6 @@ inline void Data::DecodeBuffer(bool fastDecode, int verbose){ for( int chMask = 0; chMask < MaxNChannels/2 ; chMask ++ ){ if( ((ChannelMask >> chMask) & 0x1 ) == 0 ) continue; if( verbose >= 2 ) printf("==================== Dual Channel Block, ch Mask : %d, nw : %d\n", chMask *2, nw); - if( DPPType == V1730_DPP_PHA_CODE ) { if ( DecodePHADualChannelBlock(chMask, fastDecode, verbose) < 0 ) break; } @@ -298,9 +297,8 @@ inline void Data::DecodeBuffer(bool fastDecode, int verbose){ break; } nw++; - ///printf("nw : %d ,x 4 = %d, nByte : %d \n", nw, 4*nw, nByte); + //printf("nw : %d ,x 4 = %d, nByte : %d \n", nw, 4*nw, nByte); }while(4*nw < nByte); - ///Calculate trigger rate and first and last Timestamp for(int ch = 0; ch < MaxNChannels; ch++){ if( NumEventsDecoded[ch] > 0 ) IsNotRollOverFakeAgg = true; diff --git a/DAQ/ClassDigitizer.cpp b/DAQ/ClassDigitizer.cpp index 22b5020..1e83677 100644 --- a/DAQ/ClassDigitizer.cpp +++ b/DAQ/ClassDigitizer.cpp @@ -328,8 +328,8 @@ void Digitizer::StartACQ(){ if ( AcqRun ) return; unsigned int bufferSize = CalByteForBuffer(); - if( bufferSize > 80 * 1024 * 1024 ){ - printf("============= buffer size bigger than 80 MB"); + if( bufferSize > 800 * 1024 * 1024 ){ + printf("============= buffer size bigger than 800 MB"); return; } @@ -341,7 +341,7 @@ void Digitizer::StartACQ(){ return; } - printf("\e[1m\e[33m======= Acquisition Started for Board %d\e[0m\n", boardID); + printf("\e[1m\e[33m======= Acquisition Started for Board %d - %d \e[0m\n", boardID,portID); AcqRun = true; data->ClearTriggerRate(); } @@ -351,7 +351,7 @@ void Digitizer::StopACQ(){ int ret = CAEN_DGTZ_SWStopAcquisition(handle); ret |= CAEN_DGTZ_ClearData(handle); if( ret != 0 ) ErrorMsg("something wrong when try to stop ACQ and clear buffer"); - printf("\n\e[1m\e[33m====== Acquisition STOPPED for Board %d\e[0m\n", boardID); + printf("\n\e[1m\e[33m====== Acquisition STOPPED for Board %d - %d \e[0m\n", boardID,portID); AcqRun = false; data->ClearTriggerRate(); } diff --git a/DAQ/ClassDigitizer.h b/DAQ/ClassDigitizer.h index 151b607..30204b4 100644 --- a/DAQ/ClassDigitizer.h +++ b/DAQ/ClassDigitizer.h @@ -91,6 +91,7 @@ class Digitizer{ /// ONLY WriteRegister can have ch = -1, for writting all channels /// for board setting, ignore ch void WriteRegister (Reg registerAddress, uint32_t value, int ch = -1, bool isSave2MemAndFile = true); + /// read value from digitizer and memory, and save to memory, and settingFile(if exist), /// for board setting, ignore ch uint32_t ReadRegister (Reg registerAddress, unsigned short ch = 0, bool isSave2MemAndFile = true, std::string str = "" ); diff --git a/DAQ/EventBuilder.cpp b/DAQ/EventBuilder.cpp index 141d9de..428be5e 100644 --- a/DAQ/EventBuilder.cpp +++ b/DAQ/EventBuilder.cpp @@ -1,25 +1,38 @@ #include "macro.h" #include "ClassData.h" - +#include +#include #include "TROOT.h" #include "TSystem.h" #include "TClonesArray.h" #include "TGraph.h" #include "TFile.h" #include "TTree.h" +#include "TSystem.h" #define MAX_MULTI 100 +#define MAX_File 100 #define NTimeWinForBuffer 3 +char* path_to_run="/home/bavarians/FSUDAQ_MUSIC/Run/"; +char* path_to_DAQ="/home/bavarians/FSUDAQ_MUSIC/"; +char* path_to_con="/home/bavarians/FSUDAQ_MUSIC/Conversion/"; +char* path_to_top="/home/bavarians/FSUDAQ_MUSIC/MUSIC_Topology/"; + TFile * outRootFile = NULL; TTree * tree = NULL; unsigned long long evID = 0; -unsigned short multi = 0; -unsigned short bd[MAX_MULTI] = {0}; /// boardID -unsigned short ch[MAX_MULTI] = {0}; /// chID -unsigned short e[MAX_MULTI] = {0}; /// 15 bit -unsigned long long e_t[MAX_MULTI] = {0}; /// timestamp 47 bit +unsigned short multi_evt=0; +unsigned short multi_hit=0; +unsigned short stp0[MAX_MULTI] = {0}; /// 15 bit +unsigned short stp17[MAX_MULTI] = {0}; /// 15 bit +unsigned short grid[MAX_MULTI] = {0}; /// 15 bit +unsigned short cath[MAX_MULTI] = {0}; /// 15 bit +unsigned short de_l[MAX_MULTI][16] = {{0}}; /// 15 bit +unsigned short de_r[MAX_MULTI][16] = {{0}}; /// 15 bit +unsigned short puls[MAX_MULTI][4] = {{0}}; /// 15 bit +unsigned long long e_t[MAX_MULTI] = {0}; /// timestamp 47 bit --> to get en sec *2e-9 unsigned short e_f[MAX_MULTI] = {0}; /// fine time 10 bit /// using TClonesArray to hold the trace in TGraph @@ -30,7 +43,8 @@ TGraph * trace = NULL; template void swap(T * a, T *b ); int partition(int arr[], int kaka[], TString file[], int start, int end); void quickSort(int arr[], int kaka[], TString file[], int start, int end); -void EventBuilder(Data * data, const unsigned int timeWin, bool traceOn = false, bool isLastData = false, unsigned int verbose = 0); +void extraction_map(int map[4][16]); +void EventBuilder(Data * data[],int nFile, const unsigned int timeWin, bool traceOn = false, bool isLastData = false, unsigned int verbose = 0); int main(int argc, char **argv) { @@ -40,19 +54,17 @@ int main(int argc, char **argv) { if (argc <= 3) { printf("Incorrect number of arguments:\n"); printf("%s [timeWindow] [traceOn/Off] [verbose] [inFile1] [inFile2] .... \n", argv[0]); - printf(" timeWindow : number of tick, 1 tick. default = 100 \n"); + printf(" timeWindow : in microsecond, default = 1 \n"); printf(" traceOn/Off : is traces stored \n"); printf(" verbose : > 0 for debug \n"); printf(" Output file name is contructed from inFile1 \n"); return 1; } - /// File format must be YYY...Y_runXXX_AAA_BBB_CCC.fsu - /// YYY...Y = prefix - /// XXX = runID, 3 digits - /// AAA = board Serial Number, 3 digits - /// BBB = DPPtype, 3 digits - /// CCC = over size index, 3 digits + /// File format must be Run_XXX_BB_YYY.fsu + /// XXX = 3 digits, run number + /// BB = board number, 2 digits + /// YYY = over size index, 3 digits ///============= read input unsigned int timeWindow = atoi(argv[1]); @@ -68,7 +80,8 @@ int main(int argc, char **argv) { TString outFileName = inFileName[0]; int pos = outFileName.Index("_"); pos = outFileName.Index("_", pos+1); - outFileName.Remove(pos); + outFileName.Remove(pos); + outFileName += Form("_%03u",atoi(&inFileName[0][inFileName[0].Index("B")+5])); outFileName += ".root"; printf("-------> Out file name : %s \n", outFileName.Data()); @@ -125,16 +138,27 @@ int main(int argc, char **argv) { } ///============= Set Root Tree + gSystem->cd(path_to_con); outRootFile = new TFile(outFileName, "recreate"); + // gSystem->cd(path_to_DAQ); tree = new TTree("tree", outFileName); tree->Branch("evID", &evID, "event_ID/l"); - tree->Branch("multi", &multi, "multi/s"); - tree->Branch("bd", bd, "bd[multi]/s"); - tree->Branch("ch", ch, "ch[multi]/s"); - tree->Branch("e", e, "e[multi]/s"); - tree->Branch("e_t", e_t, "e_timestamp[multi]/l"); - tree->Branch("e_f", e_f, "e_timestamp[multi]/s"); - + tree->Branch("multi_evt", &multi_evt, "multi_evt/s"); + tree->Branch("multi_hit", &multi_hit, "multi_hit/s"); + tree->Branch("de_l", de_l, "de_l[multi_evt][16]/s"); + tree->Branch("de_r", de_r, "de_r[multi_evt][16]/s"); + tree->Branch("stp0", stp0, "stp0[multi_evt]/s"); + tree->Branch("stp17", stp17, "stp17[multi_evt]/s"); + tree->Branch("grid", grid, "grid[multi_evt]/s"); + tree->Branch("cath", cath, "cath[multi_evt]/s"); + tree->Branch("puls", puls, "puls[multi_evt][4]/s"); + tree->Branch("e_t", e_t, "e_timestamp[multi_evt]/l"); + tree->Branch("e_f", e_f, "e_timestamp[multi_evt]/s"); + for(int ev=0;evBranch("traceLength", traceLength, "traceLength[multi]/s"); @@ -142,235 +166,283 @@ int main(int argc, char **argv) { arrayTrace->BypassStreamer(); } - ///============= Open input Files + + ///============= Open input Files printf("##############################################\n"); - FILE * haha = fopen(fileCat[0][0], "r"); - if( haha == NULL ){ - printf("#### Cannot open file : %s. Abort.\n", fileCat[0][0].Data()); - return -1; - } - fseek(haha, 0L, SEEK_END); - const size_t inFileSize = ftell(haha); - printf("%s | file size : %d Byte = %.2f MB\n", fileCat[0][0].Data(), (int) inFileSize, inFileSize/1024./1024.); - fclose(haha); + gSystem->cd(path_to_run); - - Data * data = new Data(); - data->DPPType = typeCat[0][0]; - data->boardSN = idCat[0]; - data->SetSaveWaveToMemory(true); + printf("#### number of files: %i \n", nFile); + FILE * haha[nFile]; + size_t inFileSize[nFile]; + for( int i = 0; i < nFile; i++){ + haha[i]= fopen(fileCat[i][0], "r"); + if( haha[i] == NULL ){ + printf("#### Cannot open file : %s. Abort.\n", fileCat[i][0].Data()); + return -1; + } + fseek(haha[i], 0L, SEEK_END); + inFileSize[i] = ftell(haha[i]); + printf("%s | file size : %d Byte = %.2f MB\n", fileCat[i][0].Data(), (int) inFileSize[i], inFileSize[i]/1024./1024.); + fclose(haha[i]); + } ///============= Main Loop - haha = fopen(inFileName[0], "r"); + gSystem->cd(path_to_run); int countBdAgg = 0; - unsigned long currentTime = 0; unsigned long oldTime = 0; - char * buffer = NULL; + Data * data[nFile]; + for( int i = 0; i < nFile; i++){ + haha[i] = fopen(inFileName[i], "r"); + data[i] = new Data(); + data[i]->DPPType ; + data[i]->boardSN = atoi(&inFileName[i][inFileName[i].Index("B")+1]); + data[i]->SetSaveWaveToMemory(true); + } + int end_of_loop=1; + + do{ + for( int i = 0; i < nFile; i++){ + // haha[i] = fopen(inFileName[i], "r"); + ///========== Get 1 aggreration for each file + oldTime = get_time(); + if( debug) printf("*********************** file pos : %d, %lu\n", (int) ftell(haha[i]), oldTime); + unsigned int word[1]; /// 4 bytes + size_t dump = fread(word, 4, 1, haha[i]); + fseek(haha[i], -4, SEEK_CUR); - ///========== Get 1 aggreration - oldTime = get_time(); - if( debug) printf("*********************** file pos : %d, %lu\n", (int) ftell(haha), oldTime); - unsigned int word[1]; /// 4 bytes - size_t dump = fread(word, 4, 1, haha); - fseek(haha, -4, SEEK_CUR); + short header = ((word[0] >> 28 ) & 0xF); + if( header != 0xA ) break; - short header = ((word[0] >> 28 ) & 0xF); - if( header != 0xA ) break; + unsigned int aggSize = (word[0] & 0x0FFFFFFF) * 4; ///byte - unsigned int aggSize = (word[0] & 0x0FFFFFFF) * 4; ///byte - - if( debug) printf("Board Agg. has %d word = %d bytes\n", aggSize/4, aggSize); + if( debug) printf("Board Agg. has %d word = %d bytes\n", aggSize/4, aggSize); - buffer = new char[aggSize]; - dump = fread(buffer, aggSize, 1, haha); - countBdAgg ++; - if( debug) printf("==================== %d Agg\n", countBdAgg); + buffer = new char[aggSize]; + dump = fread(buffer, aggSize, 1, haha[i]); + countBdAgg ++; + if( debug) printf("==================== %d Agg\n", countBdAgg); + data[i]->DecodeBuffer(buffer, aggSize,false, 0);//false + if(!data[i]->IsNotRollOverFakeAgg ) continue; + currentTime = get_time(); + if( debug) { + printf("~~~~~~~~~~~~~~~~ time used : %lu usec\n", currentTime - oldTime); + } + } + EventBuilder(data, nFile, timeWindow, traceOn, false, debug); - data->DecodeBuffer(buffer, aggSize, false, 0); - data->ClearBuffer(); - if( !data->IsNotRollOverFakeAgg ) continue; - - currentTime = get_time(); - - if( debug) { - printf("~~~~~~~~~~~~~~~~ time used : %lu usec\n", currentTime - oldTime); - data->PrintStat(); - } - - EventBuilder(data, timeWindow, traceOn, false, debug); - if( debug) printf("---------- event built : %llu \n", evID); - - //if( countBdAgg > 74) break; - }while(!feof(haha) && ftell(haha) < inFileSize); - - fclose(haha); - + for( int i = 0; i < nFile; i++){ + data[i]->ClearBuffer(); + //if( countBdAgg > 74) break; + end_of_loop= end_of_loop*(!feof(haha[i]) && ftell(haha[i]) < inFileSize[i]); + } + }while(end_of_loop==1); + for( int i = 0; i < nFile; i++){ fclose(haha[i]);} + printf("=======@@@@@@@@###############============= end of loop \n"); - EventBuilder(data, timeWindow, traceOn, true, debug); + EventBuilder(data, nFile,timeWindow, traceOn, true, debug); - + gSystem->cd(path_to_con); tree->Write(); outRootFile->Close(); - printf("========================= finsihed.\n"); printf("total events built = %llu \n", evID); printf("=======> saved to %s \n", outFileName.Data()); } -void EventBuilder(Data * data, const unsigned int timeWin, bool traceOn, bool isLastData, unsigned int verbose){ - +void EventBuilder(Data * data[],int nFile, const unsigned int timeWin, bool traceOn, bool isLastData, unsigned int verbose){ if( verbose) { printf("======================== Event Builder \n"); - data->PrintData(); } - + ///============= Set MUSIC DAQ Topology + int map[4][16]; + extraction_map(map); + int temp_index=0;double tempEn; /// find the last event timestamp; - unsigned long long firstTimeStamp = -1; - unsigned long long lastTimeStamp = 0; - unsigned long long smallestLastTimeStamp = -1; - unsigned int maxNumEvent = 0; - for( int chI = 0; chI < MaxNChannels ; chI ++){ - if( data->NumEvents[chI] == 0 ) continue; - - if( data->Timestamp[chI][0] < firstTimeStamp ) { - firstTimeStamp = data->Timestamp[chI][0]; - } - unsigned short ev = data->NumEvents[chI]-1; - if( data->Timestamp[chI][ev] > lastTimeStamp ) { - lastTimeStamp = data->Timestamp[chI][ev]; - } - if( ev + 1 > maxNumEvent ) maxNumEvent = ev + 1; - if( data->Timestamp[chI][ev] < smallestLastTimeStamp ){ - smallestLastTimeStamp = data->Timestamp[chI][ev]; - } - } - - if( maxNumEvent == 0 ) return; - - if( verbose) printf("================ time range : %llu - %llu, smallest Last %llu\n", firstTimeStamp, lastTimeStamp, smallestLastTimeStamp ); - unsigned short lastEv[MaxNChannels] = {0}; /// store the last event number for each ch - unsigned short exhaustedCh = 0; /// when exhaustedCh == MaxNChannels ==> stop - bool singleChannelExhaustedFlag = false; /// when a single ch has data but exhaused ==> stop - - do { - - /// find the 1st event - int ch1st = -1; - unsigned long long time1st = -1; - for( int chI = 0; chI < MaxNChannels ; chI ++){ - if( data->NumEvents[chI] == 0 ) continue; - if( data->NumEvents[chI] <= lastEv[chI] ) continue; - if( data->Timestamp[chI][lastEv[chI]] < time1st ) { - time1st = data->Timestamp[chI][lastEv[chI]]; - ch1st = chI; - } - } - if( !isLastData && ((smallestLastTimeStamp - time1st) < NTimeWinForBuffer * timeWin) && maxNumEvent < MaxNData * 0.6 ) break; - if( ch1st > MaxNChannels ) break; - - multi ++; - bd[multi-1] = data->boardSN; - ch[multi-1] = ch1st; - e[multi-1] = data->Energy[ch1st][lastEv[ch1st]]; - e_t[multi-1] = data->Timestamp[ch1st][lastEv[ch1st]]; - e_f[multi-1] = data->fineTime[ch1st][lastEv[ch1st]]; - if( traceOn ){ - arrayTrace->Clear("C"); - traceLength[multi-1] = (unsigned short) data->Waveform1[ch1st][lastEv[ch1st]].size(); - ///if( verbose )printf("------- trace Length : %u \n", traceLength[multi-1]); - trace = (TGraph *) arrayTrace->ConstructedAt(multi-1, "C"); - trace->Clear(); - for( int hh = 0; hh < traceLength[multi-1]; hh++){ - trace->SetPoint(hh, hh, data->Waveform1[ch1st][lastEv[ch1st]][hh]); - ///if( verbose )if( hh % 200 == 0 ) printf("%3d | %u \n", hh, data->Waveform1[ch1st][lastEv[ch1st]][hh]); - } - } - lastEv[ch1st] ++; + long long firstTimeStamp = -1; + unsigned long long lastTimeStamp = 0; + long long smallestLastTimeStamp = -1; + unsigned int maxNumEvent[nFile] ; + for( int b = 0; b < nFile ; b++){ + maxNumEvent[b] = 0; + for( int chI = 0; chI < MaxNChannels ; chI ++){ + if(data[b]->NumEvents[chI] == 0 ) continue; + if(data[b]->Timestamp[chI][0] < firstTimeStamp ) { + firstTimeStamp = data[b]->Timestamp[chI][0]; + } + unsigned short ev = data[b]->NumEvents[chI]-1; + if( data[b]->Timestamp[chI][ev] > lastTimeStamp ) { + lastTimeStamp = data[b]->Timestamp[chI][ev]; + } + if( ev + 1 > maxNumEvent[b] ) maxNumEvent[b] = ev + 1; + if( data[b]->Timestamp[chI][ev] < smallestLastTimeStamp ){ + smallestLastTimeStamp = data[b]->Timestamp[chI][ev]; + } + } + if( maxNumEvent[b] == 0 ) return; + } + if( verbose) printf("================ time range : %llu - %llu, smallest Last %llu\n", firstTimeStamp, lastTimeStamp, smallestLastTimeStamp); + unsigned short lastEv[nFile][MaxNChannels] = {0}; /// store the last event number for each ch + unsigned short exhaustedCh[nFile] = {0}; /// when exhaustedCh == MaxNChannels ==> stop + bool singleChannelExhaustedFlag[nFile] = {false}; /// when a single ch has data but exhaused ==> stop + unsigned short exhaustedBd = 0; + bool BoardExhaustedFlag[nFile] = {false}; + for( int b = 0; b < nFile ; b++){ + singleChannelExhaustedFlag[b]=false; + exhaustedCh[b]=0; + for( int c = 0; c < MaxNChannels; c++){ + lastEv[b][c]=0; + } + } + do { + /// find the 1st event + unsigned long long time1st=-1; + int ch1st=-1; int b1st=-1; + for( int b = 0; b < nFile ; b++){ + for( int chI = 0; chI < MaxNChannels ; chI ++){ + if( data[b]->NumEvents[chI] == 0 ) continue; + if( data[b]->NumEvents[chI] <= lastEv[b][chI] ) continue; + if( data[b]->Timestamp[chI][lastEv[b][chI]] < time1st ) { + time1st= data[b]->Timestamp[chI][lastEv[b][chI]]; + ch1st = chI; b1st=b; + } + } + } +//&& maxNumEvent[b] < MaxNData * 0.6 + if( !isLastData && ((smallestLastTimeStamp - time1st) < NTimeWinForBuffer * timeWin) ) break; + if( ch1st > MaxNChannels ) break; + if( b1st < 0 ) break; + + temp_index= map[b1st][ch1st]; + if(temp_index>=0){ + e_t[multi_evt]= data[b1st]->Timestamp[ch1st][lastEv[b1st][ch1st]]; + e_f[multi_evt]= data[b1st]->fineTime[ch1st][lastEv[b1st][ch1st]]; + tempEn=data[b1st]->Energy[ch1st][lastEv[b1st][ch1st]]; + if(temp_index<16){de_l[multi_evt][temp_index] = tempEn;} + if(temp_index<32 && temp_index>15){ de_r[multi_evt][temp_index] = tempEn; } + if(temp_index==500){stp0[multi_evt]= tempEn;} + if(temp_index==501){stp17[multi_evt]= tempEn;} + if(temp_index==502){grid[multi_evt]= tempEn;} + if(temp_index==503){cath[multi_evt]= tempEn;} + if(temp_index==504){puls[multi_evt][b1st]= tempEn;} + multi_hit++; + } + if( traceOn ){ + arrayTrace->Clear("C"); + traceLength[multi_evt] = (unsigned short) data[b1st]->Waveform1[ch1st][lastEv[b1st][ch1st]].size(); + trace = (TGraph *) arrayTrace->ConstructedAt(multi_evt, "C"); + trace->Clear(); + for( int hh = 0; hh < traceLength[multi_evt]; hh++){ + trace->SetPoint(hh, hh, data[b1st]->Waveform1[ch1st][lastEv[b1st][ch1st]][hh]); + } + } + lastEv[b1st][ch1st] ++; - /// build the rest of the event - exhaustedCh = 0; - singleChannelExhaustedFlag = false; - for( int chI = ch1st; chI < ch1st + MaxNChannels; chI ++){ - unsigned short chX = chI % MaxNChannels; - if( data->NumEvents[chX] == 0 ) { - exhaustedCh ++; - continue; - } - if( data->NumEvents[chX] <= lastEv[chX] ) { - exhaustedCh ++; - singleChannelExhaustedFlag = true; - continue; - } - if( timeWin == 0 ) continue; - for( int ev = lastEv[chX]; ev < data->NumEvents[chX] ; ev++){ - if( data->Timestamp[chX][ev] > 0 && (data->Timestamp[chX][ev] - e_t[0] ) < timeWin ) { - multi ++; - bd[multi-1] = data->boardSN; - ch[multi-1] = chX; - e[multi-1] = data->Energy[chX][ev]; - e_t[multi-1] = data->Timestamp[chX][ev]; - e_f[multi-1] = data->fineTime[chX][ev]; - if( traceOn ){ - traceLength[multi-1] = (unsigned short) data->Waveform1[chX][ev].size(); - trace = (TGraph *) arrayTrace->ConstructedAt(multi-1, "C"); - trace->Clear(); - for( int hh = 0; hh < traceLength[multi-1]; hh++){ - trace->SetPoint(hh, hh, data->Waveform1[chX][ev][hh]); - } - } - lastEv[chX] = ev + 1; - if( lastEv[chX] == data->NumEvents[chX] ) exhaustedCh ++; - } - } - } - - if( verbose) { - printf("=============== multi : %d , ev : %llu\n", multi, evID); - for( int ev = 0; ev < multi; ev++){ - printf("%3d, ch : %2d, %u, %llu \n", ev, ch[ev], e[ev], e_t[ev]); - } - - printf("=============== Last Ev , exhaustedCh %d \n", exhaustedCh); - for( int chI = 0; chI < MaxNChannels ; chI++){ - if( lastEv[chI] == 0 ) continue; - printf("%2d, %d %d\n", chI, lastEv[chI], data->NumEvents[chI]); - } - } - - /// fill Tree - outRootFile->cd(); - tree->Fill(); - evID++; - multi = 0; - - }while( !singleChannelExhaustedFlag || (exhaustedCh < MaxNChannels) ); - + /// build the rest of the event + exhaustedBd=0; + for( int b = 0; b < nFile ; b++){ + exhaustedCh[b] = 0; + singleChannelExhaustedFlag[b] = false; + //for( int chI = ch1st[b]; chI < ch1st[b] + MaxNChannels; chI ++){ + //unsigned short chX = chI % MaxNChannels; + for( int chI = 0; chI < MaxNChannels; chI ++){ + if( data[b]->NumEvents[chI] == 0 ) { + exhaustedCh[b] ++; + continue; + } + if(data[b]->NumEvents[chI] <= lastEv[b][chI] ) { + exhaustedCh[b] ++; + singleChannelExhaustedFlag[b] = true; + continue; + } + + if(singleChannelExhaustedFlag[b] && exhaustedCh[b] >= MaxNChannels){BoardExhaustedFlag[b]=true;} + if( timeWin == 0 ) continue; + if( BoardExhaustedFlag[b]) continue; + for( int ev = lastEv[b][chI]; ev < data[b]->NumEvents[chI] ; ev++){ + if( data[b]->Timestamp[chI][ev] > 0 && ((data[b]->Timestamp[chI][ev] - e_t[0] )*ch2ns_value*1e-9)*1e6 < timeWin ) { + temp_index= map[data[b]->boardSN][chI]; + if(temp_index>=0){ + tempEn=data[b]->Energy[chI][ev]; + if(temp_index<16 && de_l[multi_evt][temp_index]>0){multi_evt ++; de_l[multi_evt][temp_index] = tempEn;} + if(temp_index<16 && de_l[multi_evt][temp_index]==0){de_l[multi_evt][temp_index] = tempEn;} + if(temp_index<32 && temp_index>15 && de_r[multi_evt][temp_index]>0){multi_evt ++;de_r[multi_evt][temp_index] = tempEn;} + if(temp_index<32 && temp_index>15 && de_r[multi_evt][temp_index]==0){de_r[multi_evt][temp_index] = tempEn;} + if(temp_index==500 && stp0[multi_evt]>0){multi_evt ++;stp0[multi_evt]= tempEn;} + if(temp_index==500 && stp0[multi_evt]==0){stp0[multi_evt]= tempEn;} + if(temp_index==501 && stp17[multi_evt]>0){multi_evt ++;stp17[multi_evt]= tempEn;} + if(temp_index==501 && stp17[multi_evt]==0){stp17[multi_evt]= tempEn;} + if(temp_index==502 && grid[multi_evt]>0){multi_evt ++;grid[multi_evt]= tempEn;} + if(temp_index==502 && grid[multi_evt]==0){grid[multi_evt]= tempEn;} + if(temp_index==503 &&cath[multi_evt]>0){multi_evt ++;cath[multi_evt]= tempEn;} + if(temp_index==503 &&cath[multi_evt]==0){cath[multi_evt]= tempEn;} + if(temp_index==504 && puls[multi_evt][b]>0){multi_evt ++;puls[multi_evt][b]= tempEn;} + if(temp_index==504 && puls[multi_evt][b]==0){ puls[multi_evt][b] = tempEn;} + e_t[multi_evt] = data[b]->Timestamp[chI][ev]; + e_f[multi_evt] = data[b]->fineTime[chI][ev]; + multi_hit++; + } + if( traceOn ){ + traceLength[multi_evt] = (unsigned short) data[b]->Waveform1[chI][ev].size(); + trace = (TGraph *) arrayTrace->ConstructedAt(multi_evt, "C"); + trace->Clear(); + for( int hh = 0; hh < traceLength[multi_evt]; hh++){ + trace->SetPoint(hh, hh, data[b]->Waveform1[chI][ev][hh]); + } + } + lastEv[b][chI] = ev + 1; + if(lastEv[b][chI] == data[b]->NumEvents[chI] ) exhaustedCh[b] ++; + } + } + } + } + for(int b=0;b= MaxNChannels){BoardExhaustedFlag[b]=true;exhaustedBd ++;};} + multi_evt++; + if( verbose) { + printf("=============== multi : %d , ev : %llu\n", multi_evt, evID); + for( int ev = 0; ev < multi_evt; ev++){ + printf("%3d, grid time : %u, %llu \n", ev, grid[ev], e_t[ev]); + } + printf("=============== Last Ev , exhaustedBd %d \n", exhaustedBd); + for( int chI = 0; chI < MaxNChannels ; chI++){ + for( int b = 0; b < nFile ; b++){ + if(lastEv[b][chI] == 0 ) continue; + printf("board %d %2d, %d %d\n", b+1, chI, lastEv[b][chI], data[b]->NumEvents[chI]); + } + } + } + /// fill Tree + outRootFile->cd(); + tree->Fill(); + evID++; + for(int ev=0;evNumEvents[chI] == 0 ) continue; - int count = 0; - for( int ev = lastEv[chI] ; ev < data->NumEvents[chI] ; ev++){ - data->Energy[chI][count] = data->Energy[chI][ev]; - data->Timestamp[chI][count] = data->Timestamp[chI][ev]; - data->fineTime[chI][count] = data->fineTime[chI][ev]; - count++; - } - int lala = data->NumEvents[chI] - lastEv[chI]; - data->NumEvents[chI] = (lala >= 0 ? lala: 0); - } - - if( verbose > 0 ) { - printf("&&&&&&&&&&&&&&&&&&&&&&&&&& end of one event build loop\n"); - data->PrintData(); - } - + for(int b=0;bNumEvents[chI] == 0 ) continue; + int count = 0; + for( int ev = lastEv[b][chI] ; ev < data[b]->NumEvents[chI] ; ev++){ + data[b]->Energy[chI][count] = data[b]->Energy[chI][ev]; + data[b]->Timestamp[chI][count] = data[b]->Timestamp[chI][ev]; + data[b]->fineTime[chI][count] = data[b]->fineTime[chI][ev]; + count++; + } + int lala = data[b]->NumEvents[chI] - lastEv[b][chI]; + data[b]->NumEvents[chI] = (lala >= 0 ? lala: 0); + } + } } template void swap(T * a, T *b ){ @@ -378,7 +450,6 @@ template void swap(T * a, T *b ){ *b = *a; *a = temp; } - int partition(int arr[], int kaka[], TString file[], int start, int end){ int pivot = arr[start]; int count = 0; @@ -406,8 +477,26 @@ int partition(int arr[], int kaka[], TString file[], int start, int end){ } return pivotIndex; } - +void extraction_map(int map[4][16]) { + std::ifstream in; + char* file; int nlines =0; + Double_t DAQmap[4][16]; + gSystem->cd(path_to_top); + for(int b=0;b<4;b++){ + in.open(Form("Board%i.dat",b)); + nlines =0 ; + while (1) { + in >> DAQmap[b][nlines] >> map[b][nlines] ; // MeV/a.u. + if (!in.good()) break; + nlines++; + } + in.close(); + } + gSystem->cd(path_to_run); + //return 1; +} void quickSort(int arr[], int kaka[], TString file[], int start, int end){ + /// base case if (start >= end) return; /// partitioning the array diff --git a/DAQ/EventBuilder_raw.cpp b/DAQ/EventBuilder_raw.cpp new file mode 100644 index 0000000..6b8d704 --- /dev/null +++ b/DAQ/EventBuilder_raw.cpp @@ -0,0 +1,446 @@ +#include "macro.h" +#include "ClassData.h" +#include "TROOT.h" +#include "TSystem.h" +#include "TClonesArray.h" +#include "TGraph.h" +#include "TFile.h" +#include "TTree.h" +#include "TCanvas.h" +#include "TSystem.h" + +#define MAX_MULTI 100 +#define MAX_File 100 +#define NTimeWinForBuffer 3 + +char* path_to_run="/home/bavarians/FSUDAQ_MUSIC/Run/"; +char* path_to_DAQ="/home/bavarians/FSUDAQ_MUSIC/"; +char* path_to_con="/home/bavarians/FSUDAQ_MUSIC/Conversion/Raw/"; + +TFile * outRootFile = NULL; +TTree * tree = NULL; + +unsigned long long evID = 0; +unsigned short multi_evt=0; +unsigned short bd[MAX_MULTI] = {0}; /// boardPort +unsigned short ch[MAX_MULTI] = {0}; /// chID +unsigned short e[MAX_MULTI] = {0}; /// 15 bit +unsigned long long e_t[MAX_MULTI] = {0}; /// timestamp 47 bit --> to get en sec *4e-9 +unsigned short e_f[MAX_MULTI] = {0}; /// fine time 10 bit + +/// using TClonesArray to hold the trace in TGraph +TClonesArray * arrayTrace = NULL; +unsigned short traceLength[MAX_MULTI] = {0}; +TGraph * trace = NULL; + +template void swap(T * a, T *b ); +int partition(int arr[], int kaka[], TString file[], int start, int end); +void quickSort(int arr[], int kaka[], TString file[], int start, int end); +void EventBuilder_raw(Data * data[],int nFile, const unsigned int timeWin, bool traceOn = false, bool isLastData = false, unsigned int verbose = 0); + +int main(int argc, char **argv) { + + printf("=====================================\n"); + printf("=== *.fsu Events Builder ===\n"); + printf("=====================================\n"); + if (argc <= 3) { + printf("Incorrect number of arguments:\n"); + printf("%s [timeWindow] [traceOn/Off] [verbose] [inFile1] [inFile2] .... \n", argv[0]); + printf(" timeWindow : in microsecond, default = 1 \n"); + printf(" traceOn/Off : is traces stored \n"); + printf(" verbose : > 0 for debug \n"); + printf(" Output file name is contructed from inFile1 \n"); + return 1; + } + + /// File format must be Run_XXX_BB_YYY.fsu + /// XXX = 3 digits, run number + /// BB = board number, 2 digits + /// YYY = over size index, 3 digits + + ///============= read input + unsigned int timeWindow = atoi(argv[1]); + bool traceOn = atoi(argv[2]); + unsigned int debug = atoi(argv[3]); + int nFile = argc - 4; + TString inFileName[nFile]; + for( int i = 0 ; i < nFile ; i++){ + inFileName[i] = argv[i+4]; + } + + /// Form outFileName; + TString outFileName = inFileName[0]; + int pos = outFileName.Index("_"); + pos = outFileName.Index("_", pos+1); + outFileName.Remove(pos); + outFileName += Form("_%03u",atoi(&inFileName[0][inFileName[0].Index("B")+5])); + outFileName += ".root"; + printf("-------> Out file name : %s \n", outFileName.Data()); + + + printf(" Number of Files : %d \n", nFile); + for( int i = 0; i < nFile; i++) printf("%2d | %s \n", i, inFileName[i].Data()); + printf("=====================================\n"); + printf(" Time Window = %u \n", timeWindow); + printf("=====================================\n"); + + ///============= sorting file by the serial number & order + int ID[nFile]; /// serial+ order*1000; + int type[nFile]; + for( int i = 0; i < nFile; i++){ + int snPos = inFileName[i].Index("_"); + snPos = inFileName[i].Index("_", snPos+1); + int sn = atoi(&inFileName[i][snPos+1]); + type[i] = atoi(&inFileName[i][snPos+5]); + int order = atoi(&inFileName[i][snPos+9]); + ID[i] = sn + order * 1000; + } + quickSort(&(ID[0]), &(type[0]), &(inFileName[0]), 0, nFile-1); + for( int i = 0 ; i < nFile; i++){ + printf("%d | %6d | %3d | %s \n", i, ID[i], type[i], inFileName[i].Data()); + } + + ///=============== Separate files + std::vector idCat; + std::vector> typeCat; + std::vector> fileCat; + for( int i = 0; i < nFile; i++){ + if( ID[i] / 1000 == 0 ) { + std::vector temp = {inFileName[i]}; + std::vector temp2 = {type[i]}; + fileCat.push_back(temp); + typeCat.push_back(temp2); + idCat.push_back(ID[i]%1000); + }else{ + for( int p = 0; p < (int) idCat.size(); p++){ + if( (ID[i] % 1000) == idCat[p] ) { + fileCat[p].push_back(inFileName[i]); + typeCat[p].push_back(type[i]); + } + } + } + } + + printf("=====================================\n"); + for( int i = 0; i < (int) idCat.size(); i++){ + printf("............ %d \n", idCat[i]); + for( int j = 0; j< (int) fileCat[i].size(); j++){ + printf("%s | %d\n", fileCat[i][j].Data(), typeCat[i][j]); + } + } + + ///============= Set Root Tree + gSystem->cd(path_to_con); + outRootFile = new TFile(outFileName, "recreate"); + // gSystem->cd(path_to_DAQ); + tree = new TTree("tree", outFileName); + tree->Branch("evID", &evID, "event_ID/l"); + tree->Branch("multi_evt", &multi_evt, "multi_evt/s"); + tree->Branch("bd", bd, "bd[multi_evt]/s"); + tree->Branch("ch", ch, "ch[multi_evt]/s"); + tree->Branch("e", e, "e[multi_evt]/s"); + tree->Branch("e_t", e_t, "e_timestamp[multi_evt]/l"); + tree->Branch("e_f", e_f, "e_timestamp[multi_evt]/s"); + + if( traceOn ) { + arrayTrace = new TClonesArray("TGraph"); + tree->Branch("traceLength", traceLength, "traceLength[multi_evt]/s"); + tree->Branch("trace", arrayTrace, 2560000); + arrayTrace->BypassStreamer(); + } + + + ///============= Open input Files + printf("##############################################\n"); + gSystem->cd(path_to_run); + + printf("#### number of files: %i \n", nFile); + FILE * haha[nFile]; + size_t inFileSize[nFile]; + for( int i = 0; i < nFile; i++){ + haha[i]= fopen(fileCat[i][0], "r"); + if( haha[i] == NULL ){ + printf("#### Cannot open file : %s. Abort.\n", fileCat[i][0].Data()); + return -1; + } + fseek(haha[i], 0L, SEEK_END); + inFileSize[i] = ftell(haha[i]); + printf("%s | file size : %d Byte = %.2f MB\n", fileCat[i][0].Data(), (int) inFileSize[i], inFileSize[i]/1024./1024.); + fclose(haha[i]); + } + + ///============= Main Loop + gSystem->cd(path_to_run); + int countBdAgg = 0; + unsigned long currentTime = 0; + unsigned long oldTime = 0; + char * buffer = NULL; + Data * data[nFile]; + for( int i = 0; i < nFile; i++){ + haha[i] = fopen(inFileName[i], "r"); + data[i] = new Data(); + data[i]->DPPType ;//typeCat[0][0]; + // data->boardSN = atoi(&inFileName[0][inFileName[0].Index("_")+1]); //idCat[0]; + data[i]->boardSN = atoi(&inFileName[i][inFileName[i].Index("B")+1]); //idCat[0]; + data[i]->SetSaveWaveToMemory(true); + // fclose(haha[i]); + } + int end_of_loop=1; + + do{ + for( int i = 0; i < nFile; i++){ + ///========== Get 1 aggreration for each file + oldTime = get_time(); + if( debug) printf("*********************** file pos : %d, %lu\n", (int) ftell(haha[i]), oldTime); + unsigned int word[1]; /// 4 bytes + size_t dump = fread(word, 4, 1, haha[i]); + fseek(haha[i], -4, SEEK_CUR); + + short header = ((word[0] >> 28 ) & 0xF); + if( header != 0xA ) break; + + unsigned int aggSize = (word[0] & 0x0FFFFFFF) * 4; ///byte + + if( debug) printf("Board Agg. has %d word = %d bytes\n", aggSize/4, aggSize); + + buffer = new char[aggSize]; + dump = fread(buffer, aggSize, 1, haha[i]); + countBdAgg ++; + if( debug) printf("==================== %d Agg\n", countBdAgg); + data[i]->DecodeBuffer(buffer, aggSize,false, 0);//false + if(!data[i]->IsNotRollOverFakeAgg ) continue; + currentTime = get_time(); + if( debug) { + printf("~~~~~~~~~~~~~~~~ time used : %lu usec\n", currentTime - oldTime); + } + } + EventBuilder_raw(data, nFile, timeWindow, traceOn, false, debug); + + if( debug) printf("---------- event built : %llu \n", evID); + + for( int i = 0; i < nFile; i++){ + data[i]->ClearBuffer(); + //if( countBdAgg > 74) break; + end_of_loop= end_of_loop*(!feof(haha[i]) && ftell(haha[i]) < inFileSize[i]); + } + }while(end_of_loop==1); + for( int i = 0; i < nFile; i++){ fclose(haha[i]);} + + printf("=======@@@@@@@@###############============= end of loop \n"); + EventBuilder_raw(data, nFile,timeWindow, traceOn, true, debug); + + gSystem->cd(path_to_con); + tree->Write(); + outRootFile->Close(); + printf("========================= finsihed.\n"); + printf("total events built = %llu \n", evID); + printf("=======> saved to %s \n", outFileName.Data()); +} + +void EventBuilder_raw(Data * data[], int nFile, const unsigned int timeWin, bool traceOn, bool isLastData, unsigned int verbose){ + if( verbose) { + printf("======================== Event Builder \n"); + } + + /// find the last event timestamp; + long long firstTimeStamp = -1; + unsigned long long lastTimeStamp = 0; + long long smallestLastTimeStamp = -1; + unsigned int maxNumEvent[nFile] ; + for( int b = 0; b < nFile ; b++){ + maxNumEvent[b] = 0; + for( int chI = 0; chI < MaxNChannels ; chI ++){ + if(data[b]->NumEvents[chI] == 0 ) continue; + if(data[b]->Timestamp[chI][0] < firstTimeStamp ) { + firstTimeStamp = data[b]->Timestamp[chI][0]; + } + unsigned short ev = data[b]->NumEvents[chI]-1; + if( data[b]->Timestamp[chI][ev] > lastTimeStamp ) { + lastTimeStamp = data[b]->Timestamp[chI][ev]; + } + if( ev + 1 > maxNumEvent[b] ) maxNumEvent[b] = ev + 1; + if( data[b]->Timestamp[chI][ev] < smallestLastTimeStamp ){ + smallestLastTimeStamp = data[b]->Timestamp[chI][ev]; + } + } + if( maxNumEvent[b] == 0 ) return; + } + if( verbose) printf("================ time range : %llu - %llu, smallest Last %llu\n", firstTimeStamp, lastTimeStamp, smallestLastTimeStamp); + unsigned short lastEv[nFile][MaxNChannels] = {0}; /// store the last event number for each ch + unsigned short exhaustedCh[nFile] = {0}; /// when exhaustedCh == MaxNChannels ==> stop + bool singleChannelExhaustedFlag[nFile] = {false}; /// when a single ch has data but exhaused ==> stop + unsigned short exhaustedBd = 0; + bool BoardExhaustedFlag[nFile] = {false}; + for( int b = 0; b < nFile ; b++){ + singleChannelExhaustedFlag[b]=false; + exhaustedCh[b]=0; + for( int c = 0; c < MaxNChannels; c++){ + lastEv[b][c]=0; + } + } + do { + /// find the 1st event + unsigned long long time1st=-1; + int ch1st=-1; int b1st=-1; + for( int b = 0; b < nFile ; b++){ + for( int chI = 0; chI < MaxNChannels ; chI ++){ + if( data[b]->NumEvents[chI] == 0 ) continue; + if( data[b]->NumEvents[chI] <= lastEv[b][chI] ) continue; + if( data[b]->Timestamp[chI][lastEv[b][chI]] < time1st ) { + time1st= data[b]->Timestamp[chI][lastEv[b][chI]]; + ch1st = chI; b1st=b; + } + } + } + +//&& maxNumEvent[b] < MaxNData * 0.6 + if( !isLastData && ((smallestLastTimeStamp - time1st) < NTimeWinForBuffer * timeWin) ) break; + if( ch1st > MaxNChannels ) break; + if( b1st < 0 ) break; + bd[multi_evt]= data[b1st]->boardSN; + ch[multi_evt]= ch1st; + e[multi_evt]= data[b1st]->Energy[ch1st][lastEv[b1st][ch1st]]; + e_t[multi_evt]= data[b1st]->Timestamp[ch1st][lastEv[b1st][ch1st]]; + e_f[multi_evt]= data[b1st]->fineTime[ch1st][lastEv[b1st][ch1st]]; + if( traceOn ){ + arrayTrace->Clear("C"); + traceLength[multi_evt] = (unsigned short) data[b1st]->Waveform1[ch1st][lastEv[b1st][ch1st]].size(); + trace = (TGraph *) arrayTrace->ConstructedAt(multi_evt, "C"); + trace->Clear(); + for( int hh = 0; hh < traceLength[multi_evt]; hh++){ + trace->SetPoint(hh, hh, data[b1st]->Waveform1[ch1st][lastEv[b1st][ch1st]][hh]); + } + } + + multi_evt ++; + lastEv[b1st][ch1st] ++; + + /// build the rest of the event + exhaustedBd=0; + for( int b = 0; b < nFile ; b++){ + exhaustedCh[b] = 0; + singleChannelExhaustedFlag[b] = false; + //for( int chI = ch1st[b]; chI < ch1st[b] + MaxNChannels; chI ++){ + //unsigned short chX = chI % MaxNChannels; + for( int chI = 0; chI < MaxNChannels; chI ++){ + if( data[b]->NumEvents[chI] == 0 ) { + exhaustedCh[b] ++; + continue; + } + if(data[b]->NumEvents[chI] <= lastEv[b][chI] ) { + exhaustedCh[b] ++; + singleChannelExhaustedFlag[b] = true; + continue; + } + + if(singleChannelExhaustedFlag[b] && exhaustedCh[b] >= MaxNChannels){BoardExhaustedFlag[b]=true;} + + if( timeWin == 0 ) continue; + if( BoardExhaustedFlag[b]) continue; + for( int ev = lastEv[b][chI]; ev < data[b]->NumEvents[chI] ; ev++){ + if( data[b]->Timestamp[chI][ev] > 0 && ((data[b]->Timestamp[chI][ev] - e_t[0] )*ch2ns_value*1e-9)*1e6 <= timeWin ) { + bd[multi_evt] = data[b]->boardSN; + ch[multi_evt] = chI; + e[multi_evt] = data[b]->Energy[chI][ev]; + e_t[multi_evt] = data[b]->Timestamp[chI][ev]; + e_f[multi_evt] = data[b]->fineTime[chI][ev]; + if( traceOn ){ + traceLength[multi_evt] = (unsigned short) data[b]->Waveform1[chI][ev].size(); + trace = (TGraph *) arrayTrace->ConstructedAt(multi_evt, "C"); + trace->Clear(); + for( int hh = 0; hh < traceLength[multi_evt]; hh++){ + trace->SetPoint(hh, hh, data[b]->Waveform1[chI][ev][hh]); + } + } + lastEv[b][chI] = ev + 1; + multi_evt ++; + if(lastEv[b][chI] == data[b]->NumEvents[chI] ) exhaustedCh[b] ++; + } + } + } + } + for(int b=0;b= MaxNChannels){BoardExhaustedFlag[b]=true;exhaustedBd ++;};} + + if( verbose) { + printf("=============== multi : %d , ev : %llu\n", multi_evt, evID); + for( int ev = 0; ev < multi_evt; ev++){ + printf("%3d, bd, ch : %2d, %2d, %u, %llu \n", ev, bd[ev], ch[ev], e[ev], e_t[ev]); + } + printf("=============== Last Ev , exhaustedBd %d \n", exhaustedBd); + for( int chI = 0; chI < MaxNChannels ; chI++){ + for( int b = 0; b < nFile ; b++){ + if(lastEv[b][chI] == 0 ) continue; + printf("board %d %2d, %d %d\n", b+1, chI, lastEv[b][chI], data[b]->NumEvents[chI]); + } + } + } + /// fill Tree + outRootFile->cd(); + tree->Fill(); + evID++; + multi_evt=0; + }while(exhaustedBd < nFile && exhaustedBdNumEvents[chI] == 0 ) continue; + int count = 0; + for( int ev = lastEv[b][chI] ; ev < data[b]->NumEvents[chI] ; ev++){ + data[b]->Energy[chI][count] = data[b]->Energy[chI][ev]; + data[b]->Timestamp[chI][count] = data[b]->Timestamp[chI][ev]; + data[b]->fineTime[chI][count] = data[b]->fineTime[chI][ev]; + count++; + } + int lala = data[b]->NumEvents[chI] - lastEv[b][chI]; + data[b]->NumEvents[chI] = (lala >= 0 ? lala: 0); + } + } +} + +template void swap(T * a, T *b ){ + T temp = * b; + *b = *a; + *a = temp; +} + +int partition(int arr[], int kaka[], TString file[], int start, int end){ + int pivot = arr[start]; + int count = 0; + for (int i = start + 1; i <= end; i++) { + if (arr[i] <= pivot) count++; + } + /// Giving pivot element its correct position + int pivotIndex = start + count; + swap(&arr[pivotIndex], &arr[start]); + swap(&file[pivotIndex], &file[start]); + swap(&kaka[pivotIndex], &kaka[start]); + + /// Sorting left and right parts of the pivot element + int i = start, j = end; + while (i < pivotIndex && j > pivotIndex) { + while (arr[i] <= pivot) {i++;} + while (arr[j] > pivot) {j--;} + if (i < pivotIndex && j > pivotIndex) { + int ip = i++; + int jm = j--; + swap( &arr[ip], &arr[jm]); + swap(&file[ip], &file[jm]); + swap(&kaka[ip], &kaka[jm]); + } + } + return pivotIndex; +} + +void quickSort(int arr[], int kaka[], TString file[], int start, int end){ + + /// base case + if (start >= end) return; + /// partitioning the array + int p = partition(arr, kaka, file, start, end); + /// Sorting the left part + quickSort(arr, kaka, file, start, p - 1); + /// Sorting the right part + quickSort(arr, kaka, file, p + 1, end); +} diff --git a/DAQ/Makefile b/DAQ/Makefile index 9450db1..f86f6e0 100755 --- a/DAQ/Makefile +++ b/DAQ/Makefile @@ -15,25 +15,31 @@ OBJS = influxdb.o startStopDialog.o programSetting.o triggerSummary.o registerSe ######################################################################### -all : ../test ../FSUDAQ ../test_indep ../Analysis/EventBuilder +all : ../Acquisition ../Analysis ../FSUDAQ /EventBuilder ../Analysis/EventBuilder_raw ../Plotting + ##../testStartAtSameTime clean : - /bin/rm -f $(OBJS) test FSUDAQ test_indep EventBuilder FSUDAQDict.cxx *.pcm + /bin/rm -f $(OBJS) Acquisition FSUDAQ EventBuilder EventBuilder_raw Plotting FSUDAQDict.cxx *.pcm + ##testStartAtSameTime ClassDigitizer.o : ClassDigitizer.cpp ClassDigitizer.h RegisterAddress.h macro.h ClassData.h $(CC) $(COPTS) -c ClassDigitizer.cpp -../test : test.cpp ClassDigitizer.o influxdb.o - @echo "--------- making test" - $(CC) $(COPTS) -o ../test test.cpp ClassDigitizer.o influxdb.o $(CAENLIBS) $(ROOTLIBS) -lcurl +../Acquisition : Acquisition.cpp ClassDigitizer.o influxdb.o + @echo "--------- making Acquisition" + $(CC) $(COPTS) -o ../Acquisition Acquisition.cpp ClassDigitizer.o influxdb.o $(CAENLIBS) $(ROOTLIBS) -lcurl ../Analysis/EventBuilder : EventBuilder.cpp ClassData.h @echo "--------- making EventBuilder" - $(CC) $(COPTS) -o ../Analysis/EventBuilder EventBuilder.cpp $(ROOTLIBS) - -../test_indep : test_indep.cpp RegisterAddress.h macro.h - @echo "--------- making test_indep" - $(CC) $(COPTS) -o ../test_indep test_indep.cpp $(CAENLIBS) + $(CC) $(COPTS) -o ../Analysis/EventBuilder EventBuilder.cpp $(CAENLIBS) $(ROOTLIBS) -lcurl + +../Analysis/EventBuilder_raw : EventBuilder_raw.cpp ClassData.h + @echo "--------- making EventBuilder_raw" + $(CC) $(COPTS) -o ../Analysis/EventBuilder_raw EventBuilder_raw.cpp $(CAENLIBS) $(ROOTLIBS) -lcurl + +../Plotting : Plotting.cpp ClassData.h + @echo "--------- making Plotting" + $(CC) $(COPTS) -o ../Plotting Plotting.cpp $(CAENLIBS) $(ROOTLIBS) -lcurl ../FSUDAQ : FSUDAQDict.cxx $(OBJS) ClassData.h @echo "----------- creating FSUDAQ" @@ -85,4 +91,7 @@ startStopDialog.o: startStopDialog.h startStopDialog.cpp #BoxScore : src/BoxScore.c Class/ClassDigitizer.h Class/FileIO.h Class/GenericPlane.h Class/HelioTarget.h Class/IsoDetect.h Class/HelioArray.h Class/MCPClass.h # g++ -std=c++17 -pthread src/BoxScore.c -o BoxScore $(DEPLIBS) $(ROOTLIBS) +#../testStartAtSameTime : testStartAtSameTime.cpp ClassDigitizer.o influxdb.o +# @echo "--------- making testStartAtSameTime" +# $(CC) $(COPTS) -o ../testStartAtSameTime testStartAtSameTime.cpp ClassDigitizer.o influxdb.o $(CAENLIBS) $(ROOTLIBS) -lcurl diff --git a/DAQ/Plotting.cpp b/DAQ/Plotting.cpp new file mode 100644 index 0000000..e21036f --- /dev/null +++ b/DAQ/Plotting.cpp @@ -0,0 +1,177 @@ +#include "macro.h" +#include "ClassData.h" +#include "TH1.h" +#include "TH2.h" +#include "TStyle.h" +#include "TCanvas.h" +#include "TFile.h" +#include "TChain.h" +#include "TSystem.h" +#include "TTree.h" +#include +#include "TApplication.h" + +char* path_to_con="/home/bavarians/FSUDAQ_MUSIC/Conversion/"; + +TH1I * heleft[MaxNChannels]; +TH1I * heright[MaxNChannels]; +TH1I * MultiEVT; +TH1I * MultiHIT; +TH2F* MapFull ; +TH2F* MapLeft; +TH2F* MapRight; +TH2F* S0A1l; +TH2F* S0grid; +TH2F* S0cath; +TH2F* A1A2; +TH2F* gridcath; +TH2F* MapTime; + +//IF SILICON DETECTOR +/*TH1F* E_histo ; +TH1F* dE_histo; +TH2F* dEE; +TH2F* si_de_time ; +TH2F* si_e_time;*/ + +TCanvas* csegLeft; +TCanvas* csegRight; +TCanvas* c; +TCanvas* cmult; +TCanvas* cmap; +TCanvas* cantime; + +#define MAX_MULTI 100 +unsigned long long evID ; +unsigned short multi_evt; +unsigned short multi_hit; +unsigned short stp0[MAX_MULTI]; /// 15 bit +unsigned short stp17[MAX_MULTI]; /// 15 bit +unsigned short grid[MAX_MULTI]; /// 15 bit +unsigned short cath[MAX_MULTI] ; /// 15 bit +unsigned short de_l[MAX_MULTI][16] ; /// 15 bit +unsigned short de_r[MAX_MULTI][16] ; /// 15 bit +unsigned short puls[MAX_MULTI][4]; /// 15 bit +unsigned long long e_t[MAX_MULTI]; /// timestamp 47 bit --> to get en sec *2e-9 +unsigned short e_f[MAX_MULTI]; /// fine time 10 bit + +int main(int argc, char* argv[]){ + + printf("=====================================\n"); + printf("=== Data Visualization ===\n"); + printf("=====================================\n"); + if (argc < 2) { + printf("Incorrect number of arguments:\n"); + printf("%s [RunId] \n", argv[0]); + printf("%s [Number of subfiles] \n", argv[1]); + return 1; + } + if (argc > 1) { + TApplication theApp("App",&argc, argv); + int Rid= atoi(argv[1]); + int Nfiles = atoi(argv[2]); + //""""""""""""""""""""" + //Accesing run + //""""""""""""""""""""" + gSystem->cd(path_to_con); + //FILE * haha[Nfiles]; TString inFileName; + char* inFileName; + TChain* MusicTree = new TChain("tree"); + for(int f=0;f9 && f<100){inFileName= Form("Run_00%i_0%i.root", Rid, f);} + if(f>99 && f<1000){inFileName= Form("Run_00%i_%i.root", Rid, f);} + printf("input file %s \n", inFileName); + //haha[f] = fopen(inFileName, "r"); + MusicTree->Add(inFileName); + } + MusicTree->SetBranchAddress("evID", &evID); + MusicTree->SetBranchAddress("multi_evt",&multi_evt); MusicTree->SetBranchAddress("multi_hit", &multi_hit); + MusicTree->SetBranchAddress("de_l", de_l); MusicTree->SetBranchAddress("de_r", de_r); + MusicTree->SetBranchAddress("stp0", stp0); MusicTree->SetBranchAddress("stp17", stp17); + MusicTree->SetBranchAddress("grid", grid); MusicTree->SetBranchAddress("cath" ,cath); + MusicTree->SetBranchAddress("puls", puls); + MusicTree->SetBranchAddress("e_t",e_t); MusicTree->SetBranchAddress("e_f", e_f); + int nStat = MusicTree->GetEntries(); + printf("number of Tree entries %i \n", nStat); + + //""""""""""""""""""""" + //Plot definition + //""""""""""""""""""""" + csegLeft= new TCanvas("csegLeft","csegLeft",1600,1600);csegLeft->Divide(4,4); + csegRight= new TCanvas("csegRight","csegRight",1600,1600);csegRight->Divide(4,4); + c= new TCanvas("c","c",1600,1600);c->Divide(2,2); + cmult= new TCanvas("cmult","cmult",1600,1600);cmult->Divide(2,2); + cmap= new TCanvas("cmap","cmap",900,1600);cmap->Divide(1,3); + cantime= new TCanvas("cantime","cantime",400,400); + cantime->cd(); + + double Er[2]={0., 16000}; double Timer[2]={0., 5000}; + double bin_raw=2; double bin_raw_time=0.1; + int Nbins = int((Er[1]-Er[0])/bin_raw); + int NbinsTime = int((Timer[1]-Timer[0])/ bin_raw_time); + S0A1l = new TH2F("S0A1l",";#DeltaE_{0} (a.u.); #DeltaE_{1} left (a.u.)",Nbins, Er[0], Er[1], Nbins, Er[0], Er[1]); + S0cath = new TH2F("S0cath",";cathode (a.u.);#DeltaE_{0} (a.u.)",Nbins, Er[0], Er[1],Nbins, Er[0], Er[1]); + S0grid= new TH2F("S0grid",";grid (a.u.);#DeltaE_{0} (a.u.)", Nbins, Er[0], Er[1],Nbins, Er[0], Er[1]); + A1A2 = new TH2F("A1A2",";#DeltaE_{1} (a.u.);#DeltaE_{2} (a.u.)",Nbins, Er[0], Er[1],Nbins, Er[0], Er[1]); + gridcath= new TH2F("gridcath",";grid (a.u.);cathode (a.u.)", Nbins, Er[0], Er[1],Nbins, Er[0], Er[1]); + MapLeft= new TH2F("MapLeft","Left;Strip;#DeltaE (a.u.)", 18,0,18,Nbins, Er[0], Er[1]); + MapRight = new TH2F("MapRight","Right;Strip;#DeltaE (a.u.)", 18,0,18,Nbins, Er[0], Er[1]); + MapFull = new TH2F("MapFull","Long segments;Strip;#DeltaE (a.u.)", 18,0,17,Nbins, Er[0], Er[1]); + MapTime = new TH2F("MapTime",";Time event (ms); grid = 0 & Pulser = 5+Board*5", NbinsTime,Timer[0],Timer[1],25,0,25); + MultiEVT = new TH1I("MultiEVT",";Event multiplicity", 10, 0, 10); + MultiHIT= new TH1I("MultiHIT",";DAQ Channel Hit multiplicity", 100, 0, 100); + for(int c=0;cDraw("multi_evt>>MultiEVT"); + MusicTree->Draw("multi_hit>>MultiHIT"); + for(int i = 0;iGetEntry(i); + if(multi_evt*multi_hit>0){ + for(int ev=0;evFill(grid[ev],stp0[ev]); S0cath->Fill(cath[ev],stp0[ev]); + gridcath->Fill(grid[ev],cath[ev]); + MapRight->Fill(0.,stp0[ev]); MapLeft->Fill(0.,stp0[ev]); + MapRight->Fill(17,stp17[ev]); MapLeft->Fill(17,stp17[ev]); + A1A2->Fill(de_l[ev][0],de_r[ev][1]); S0A1l->Fill(stp0[ev], de_l[ev][0]); + for( int c = 0; c Fill(de_l[ev][c]); heright[c]->Fill(de_r[ev][c]); + MapRight->Fill(c+1,de_r[ev][c]); MapLeft->Fill(c+1,de_l[ev][c]); + if(c%2==0){MapFull->Fill(c+1, de_l[ev][c]);} + if(c%2==1){MapFull->Fill(c+1, de_r[ev][c]);} + } + if(e_t[ev]*ch2ns_value*1e-90){MapTime->Fill(e_t[ev]*ch2ns_value*1e-6,0);} + for(int b = 0; b 0){MapTime->Fill(e_t[ev]*ch2ns_value*1e-6,5+b*5);} + } + } + } + } + } + printf("Enter Ctrl+C to stop ..."); + //""""""""""""""""""""" + //Plotting + //""""""""""""""""""""" + gStyle->SetPalette(kThermometer); + c->cd(1);S0grid->Draw("colz");S0grid->GetXaxis()->CenterTitle();S0grid->GetYaxis()->CenterTitle(); + c->cd(2);S0cath->Draw("colz");S0cath->GetXaxis()->CenterTitle();S0cath->GetYaxis()->CenterTitle(); + c->cd(3); S0A1l->Draw("colz"); S0A1l->GetXaxis()->CenterTitle(); S0A1l->GetYaxis()->CenterTitle(); + c->cd(4);A1A2->Draw("colz");A1A2->GetXaxis()->CenterTitle();A1A2->GetYaxis()->CenterTitle(); + cmult->cd(1);gridcath->Draw("colz");gridcath->GetXaxis()->CenterTitle();gridcath->GetYaxis()->CenterTitle(); + cantime->cd();MapTime->Draw("colz");MapTime->GetXaxis()->CenterTitle();MapTime->GetYaxis()->CenterTitle(); + cmap->cd(1);MapLeft->Draw("colz");MapLeft->GetXaxis()->CenterTitle();MapLeft->GetYaxis()->CenterTitle(); + cmap->cd(2);MapRight->Draw("colz");MapRight->GetXaxis()->CenterTitle();MapRight->GetYaxis()->CenterTitle(); + cmap->cd(3);MapFull->Draw("colz");MapFull->GetXaxis()->CenterTitle();MapFull->GetYaxis()->CenterTitle(); + for( int i = 0; i cd(i+1); heleft[i]->Draw("h");heleft[i]->GetXaxis()->CenterTitle(); + csegRight->cd(i+1); heright[i]->Draw("h");heright[i]->GetXaxis()->CenterTitle(); + } + cmult->cd(3);MultiEVT->Draw("h");MultiEVT->GetXaxis()->CenterTitle(); + cmult->cd(4);MultiHIT->Draw("h");MultiHIT->GetXaxis()->CenterTitle(); + theApp.Run(); + return 1; + } +} diff --git a/DAQ/RegisterAddress.h b/DAQ/RegisterAddress.h index 508febd..e23306e 100644 --- a/DAQ/RegisterAddress.h +++ b/DAQ/RegisterAddress.h @@ -264,7 +264,8 @@ namespace Register { const Reg TriggerHoldOffWidth ("TriggerHoldOffWidth" , 0x1074); /// R/W OK const Reg PeakHoldOff ("PeakHoldOff" , 0x1078); /// R/W OK const Reg ShapedTriggerWidth ("ShapedTriggerWidth" , 0x1084); /// R/W not sure - const Reg DPPAlgorithmControl2_G ("DPPAlgorithmControl2_G" , 0x10A0, 0, 1); /// R/W OK + const Reg DPPAlgorithmControl2_G ("DPPAlgorithmControl2_G" , 0x10A0, 0); /// R/W OK + const Reg DPPAlgorithmControl22_G ("DPPAlgorithmControl22_G" , 0x10AC); /// R/W OK const Reg FineGain ("FineGain" , 0x10C4); /// R/W OK } diff --git a/DAQ/macro.h b/DAQ/macro.h index 19ad7b6..6043700 100644 --- a/DAQ/macro.h +++ b/DAQ/macro.h @@ -2,10 +2,10 @@ #define MACRO_H #define MaxNPorts 4 -#define MaxNBoards 22 +#define MaxNBoards 4 #define MaxNChannels 16 #define MaxRecordLength 0x3fff * 8 -#define MaxSaveFileSize 1024 * 1024 * 1024 * 2 +#define MaxSaveFileSize 1024 * 1024 * 1024 * 1.0 #define SETTINGSIZE 2048 diff --git a/DAQ/testStartAtSameTime.cpp b/DAQ/testStartAtSameTime.cpp new file mode 100644 index 0000000..0baeabd --- /dev/null +++ b/DAQ/testStartAtSameTime.cpp @@ -0,0 +1,79 @@ + +#include // std::cout +#include // std::thread +#include // std::mutex, std::unique_lock +#include // std::condition_variable +#include // time in nano-sec +#include // usleep + +#define nTh 5 + +std::mutex mtx[nTh]; +std::condition_variable cv; +bool ready = false; + +timespec ts[nTh]; + +void print_id(int id) { + std::unique_lock lck(mtx[id]); + while (!ready ){ + printf("waiting for unlock %d\n", id); + cv.wait(lck); + } + cv.notify_all(); + + clock_gettime(CLOCK_REALTIME, &ts[id]); + printf("----thread %d ready. %ld ns\n", id, ts[id].tv_nsec); + + usleep(2000*2000); + + printf("thread %d finished.\n", id); + +} + +void go() { + ready = true; + cv.notify_all(); +} + +int main(){ + + std::thread threads[nTh]; + + for (int i = 0; i < nTh; ++i){ + threads[i] = std::thread(print_id, i); + } + + printf("%d threads ready to race...\n", nTh); + + usleep(1000*1000); + + go(); // go! + + for (auto& th : threads) th.join(); + + printf("=========== finsihed.\n"); + + long avg = 0; + for( int i =0; i < nTh ; i++) avg += ts[i].tv_nsec; + avg = avg/nTh; + + long min , max; + + for( int i =0; i < nTh; i++) { + if( i == 0 ){ + min = ts[i].tv_nsec; + max = ts[i].tv_nsec; + continue; + } + if( min > ts[i].tv_nsec) min = ts[i].tv_nsec; + if( max < ts[i].tv_nsec) max = ts[i].tv_nsec; + } + + printf(" avg : %ld\n", avg); + printf(" min : %ld, %ld\n", min, avg - min); + printf(" max : %ld, %ld\n", max, max - avg); + printf(" diff : %ld\n", max-min); + + return 0; +} diff --git a/MUSIC_Topology/Board0.dat b/MUSIC_Topology/Board0.dat new file mode 100644 index 0000000..61822e4 --- /dev/null +++ b/MUSIC_Topology/Board0.dat @@ -0,0 +1,17 @@ +0 503 +1 -1 +2 1 +3 -1 +4 500 +5 504 +6 5 +7 -1 +8 0 +9 -1 +10 9 +11 -1 +12 17 +13 13 +14 -1 +15 502 + diff --git a/MUSIC_Topology/Board1.dat b/MUSIC_Topology/Board1.dat new file mode 100644 index 0000000..4453723 --- /dev/null +++ b/MUSIC_Topology/Board1.dat @@ -0,0 +1,16 @@ +0 2 +1 -1 +2 16 +3 -1 +4 21 +5 504 +6 20 +7 -1 +8 8 +9 -1 +10 24 +11 -1 +12 27 +13 28 +14 -1 +15 14 diff --git a/MUSIC_Topology/Board2.dat b/MUSIC_Topology/Board2.dat new file mode 100644 index 0000000..59cbffb --- /dev/null +++ b/MUSIC_Topology/Board2.dat @@ -0,0 +1,16 @@ +0 19 +1 -1 +2 3 +3 -1 +4 6 +5 504 +6 7 +7 -1 +8 25 +9 -1 +10 11 +11 -1 +12 12 +13 15 +14 -1 +15 10 diff --git a/MUSIC_Topology/Board3.dat b/MUSIC_Topology/Board3.dat new file mode 100644 index 0000000..a56cc1a --- /dev/null +++ b/MUSIC_Topology/Board3.dat @@ -0,0 +1,16 @@ +0 4 +1 -1 +2 18 +3 -1 +4 23 +5 504 +6 22 +7 -1 +8 29 +9 -1 +10 26 +11 -1 +12 31 +13 30 +14 -1 +15 501 diff --git a/README/README.md b/README/README.md new file mode 100644 index 0000000..61b3e5b --- /dev/null +++ b/README/README.md @@ -0,0 +1,112 @@ +## Introduction (First Version) + +The FSUDAQ_MUSIC is an ONGOING online and offline aquisition for CAEN x725 digitizers with DPP-PHA firmware for MUSIC set-up at ATLAS/Argonne National Laboratory. +It is based on CERN_ROOT/C++. The x730 digitizer and the DPP-PSD firmware are also possible. + +Additional inforamtion in https://fsunuc.physics.fsu.edu/wiki/index.php/CAEN_digitizer#FSU_DAQ + +## Required Library +1. CAENComm 1.4+ +2. CAENVMELib 2.5+ +3. CAENDigitizer 2.12+ +4. CAEN A3818 Driver 1.61+ (for optical link) +5. CERN ROOT 6 +6. libcurl4-nss-dev (for the libcurl, used in InfluxDB class) +7. InfluxDB 1.8 (recommanded for trigger rate, optional for database) + +## Folder Structure +FSUDAQ_MUSIC \ + ├── Analysis \ + ├── Conversion \ + | └── Raw \ + ├── DAQ \ + ├── MUSIC_Topology\ + ├── README \ + └── Run \ + +The parent folder FSUDAQ_MUSIC should be placed on the Home directory. +Information available in README/ folder. + +All source codes are in DAQ/ folder. +The key codes are +1. ClassData.h +2. RegisterAddress.h +3. ClassDigitizer.h/cpp +4. Acquisition.cpp +5. EventBuilder.cpp EventBuilder_raw.cpp +6. Plotting.cpp + +4. The Acquisition.cpp is the main code for online acquisition. It controls, readouts digitizers and stores the data in Run/ folder. + +5. The EventBuilder_raw.cpp and EventBuilder.cpp are the codes for online /offline event building with the raw DAQ topology and the MUSIC setup toplogy, respectively. +Saved raw run .fsu files (in Run/) are converted in TTree .root run files in Conversion/Raw/ and Conversion/ for EventBuilder_raw.cpp and EventBuilder.cpp, respectively. +Compiled scripts are stored in Analysis/ folder. + +6. The Plotting.cpp is a code for online or offline data visualization from the converted .root run files in Conversion/, requiring the MUSIC setup toplogy. + + +The MUSIC setup toplogy is defined in MUSIC_Topology/. +--> see description in README/Topology_MUSIC_read_me.md + + +## To Compile (--> according to DAQ/Makefile) +> cd DAQ/; make ../Acquisition;cd ../; +> cd DAQ/; make ../Analysis/EventBuilder_raw;cd ../; +> cd DAQ/; make ../Analysis/EventBuilder;cd ../; +> cd DAQ/; make ../Plotting;cd ../; + +Executables produced for each code. + + + +######## +# Usages +######## + + +## Acquisition +--> Input = [Run Time in second, 0 for infinite one] [Run number] + +Number of available digitizers defined at start +--> nDig +Data taking done in parallel with the function: +--> func(Digitizer * dig, double RunTime, int Rid, int Bid) +All digitizers start at close time (~dT tens of microseconds) + +Assignement of registers value done through 2 functions +--> boardSetParameters //Parameters usually tuned at the start of a MUSIC experiment with the help of CoMPASS software +--> boardCommonParameters //Standard parameters for MUSIC setup +Details on how to assign the registers values are given in +--> README/Register_inputs_readme.md + +Raw data are stored in Run/, with the path defined at start +--> path_to_run +A file per board and files size limit is 1 GB (defined with MaxSaveFileSize in DAQ/macro.h ) +--> Run_00#_B#_###.fsu + + +## EventBuilder_raw and EventBuilder +--> Input = [Time window in microsecond] [Trace ==0, off] [verbose 0/1] [list of raw run .fsu filenames ...] + +Building of events in readable format, i.e. oot TTree 'tree' (see defined tree structures). + +Raw conversion stores within the time window the lists of energy/time/board/channel. The number of DAQ channel hits corresponds to +-->multi_evt + +Final conversion stores within the time window the physical events with MUSIC inputs (energies of left/right segments, grid, cathode, strip0, strip17,..., and times, pulsers...). +The number of events within the time window is +-->multi_evt +The number of MUSIC signals hits for each event (e.g. std value is 16+4(+4puls)) is +-->multi_hit + +MUSIC setup toplogy path is defined at start +--> path_to_top +Converted root files are stored in Conversion/, with the path defined at start +--> path_to_con + + +## Plotting +--> Input = [Run number] [number of run_subfiles] + +Standard MUSIC histograms for PID, beam trajectory and segment maps (2x16), event built multiplicities and time structure (if pulser input per board). +Additional (like Silicon PID..) histograms to be defined at the start of the script. diff --git a/README/Register_inputs_readme.md b/README/Register_inputs_readme.md new file mode 100644 index 0000000..fd7fe7c --- /dev/null +++ b/README/Register_inputs_readme.md @@ -0,0 +1,50 @@ +## Introduction +Assignement of registers value done in DAQ/Acquisition.cpp, +parameters are usually tuned at the start of a MUSIC experiment with the help of CoMPASS software. + +Assigned registers saved in +--> reg_Board%i.txt + +## Usage +Digitizer class function +--> dig->WriteRegister(Register::#DPP::#PHA::#name, #value_in_hexadecimal, #channel_index) + +To access registers values, looked in CoMPASS software (or if saved in reg_Board%i.txt) with register address "Reg" defined by +--> 0x#### + +Aggregate registers +--> MaxAggregatePerBlockTransfer //Reg=0xEF1C +--> NumberEventsPerAggregate_G //Reg=0x1034 + +Standard registers defined and assigned in +--> boardCommonParameters(Digitizer * dig) + +Specific registers per MUSIC experiment defined and assigned in +--> boardSetParameters(...) +where inputs defined in main function +--> double BoardConfigurationval //Reg=0x8000 +--> double DPPAlgoCtrl //Reg=0x1080 +--> double DPPAlgoCtrl_10A0 //Reg=0x10A0 +--> double DPPAlgoCtrl_10AC //Reg=0x10AC +--> double ShapedTriggerWidthVal //Reg=0x1084 in steps of 16ns, 96=6*16 +--> double InputSec[7] // Corresponding to CoMPASS Inputs Section + 0. Not used + 1. //Reg=0x1020 RecordLength input N such length (ns) == N*8*4 + 2. //Reg=0x1038 PreTrigger in steps of 16ns, input N such length (ns) == N*4*4 + 3. Not used + 4. Not used + 5. //Reg=0x1098 DCoffset DC% = 1 - input/65535 (ChannelDCOffset) + 6. //Reg=0x1028 CoarseGain 0=x1 or 1=x4 (InputDynamicRange) +--> double DiscriSec[4] // Corresponding to CoMPASS Discriminator Section + 0. //Reg=0x106C TriggerThreshold in lsb + 1. //Reg=0x1074 TriggerHoldOffWidth in steps of 16ns + 2. //Reg=0x1054 FastDiscriSmooth, e.g. 20=64samp, 63=128samp, (RCCR2SmoothingFactor) + 3. //Reg=0x1058 InputRiseTime in steps of 16ns +--> double TrapSec[7] // Corresponding to CoMPASS Trapezoid Section + 0. //Reg=0x105C RiseTime in steps of 16ns + 1. //Reg=0x1060 FlatTop in steps of 16ns + 2. //Reg=0x1068 PoleZero in steps of 16ns (DecayTime) + 3. //Reg=0x1064 PeakingTime in steps of 16ns + 4. Not used + 5. //Reg=0x1078 PeakHoldOff in steps of 16ns + 6. //Reg=0x10C4 fine gain, eg 1==0x00006C3A (FineGain) diff --git a/README/Topology_MUSIC_read_me.md b/README/Topology_MUSIC_read_me.md new file mode 100644 index 0000000..6e08793 --- /dev/null +++ b/README/Topology_MUSIC_read_me.md @@ -0,0 +1,21 @@ +## Introduction +The topology of the DAQ w.r.t detection inputs (MUSIC signals, pulser, additional Silicon signals...) is given in a file per board +--> Board#.dat +Files and associated topology information are extracted and used by DAQ/EventBuilder.cpp to build back events from DAQ channels to physics signals. +Used function in DAQ/EventBuilder.cpp +--> extraction_map(int map[4][16]) + +## Path to files +FSUDAQ_MUSIC/MUSIC_Topology/Board#.dat + +## File Structure --> 2 columns +DAQ channel (0->15) | MUSIC Segment + +## Correspondance MUSIC Segment to physics inputs +500 == Strip 0 +501 == Strip 17 +502 == Grid +503 == Cathode +504 == Pulse +0->15 == left side +16->31 == right side