From ee2962d4f9357b6ae8b67a608bdd4768ee8cfba4 Mon Sep 17 00:00:00 2001 From: "Ryan@SOLARIS_testStation" Date: Thu, 18 Jul 2024 19:02:22 -0400 Subject: [PATCH] added a Bin2Root eventbuilder --- .gitignore | 7 ++ Bin2Root.cpp | 263 +++++++++++++++++++++++++++++++++++++++++++++++++++ BinReader.h | 71 +++++++------- Makefile | 24 +++++ test.C | 79 ++++++++++------ 5 files changed, 382 insertions(+), 62 deletions(-) create mode 100644 .gitignore create mode 100644 Bin2Root.cpp create mode 100644 Makefile diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9ad8b63 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.o +*.fsu +*.root + +data + +Bin2Root \ No newline at end of file diff --git a/Bin2Root.cpp b/Bin2Root.cpp new file mode 100644 index 0000000..26e4239 --- /dev/null +++ b/Bin2Root.cpp @@ -0,0 +1,263 @@ +#include "BinReader.h" + +#include /** struct timeval, select() */ + +inline unsigned int getTime_us(){ + unsigned int time_us; + struct timeval t1; + struct timezone tz; + gettimeofday(&t1, &tz); + time_us = (t1.tv_sec) * 1000 * 1000 + t1.tv_usec; + return time_us; +} + + +#include "TFile.h" +#include "TTree.h" +#include "TMacro.h" + +#define MAX_TRACE_LENGTH 2000 +#define MAX_MULTI 100 +#define NMINARG 5 +#define debug 0 + +//^############################################################# +//^############################################################# +int main(int argc, char **argv) { + + printf("=========================================\n"); + printf("=== CoMPASS Binary to root ===\n"); + printf("=========================================\n"); + if (argc < NMINARG) { + printf("Incorrect number of arguments:\n"); + printf("%s [timeWindow] [withTrace] [outFile] [inFile1] [inFile2] .... \n", argv[0]); + printf(" timeWindow : in ns, -1 = no event building \n"); + printf(" withTrace : 0 for no trace, 1 for trace \n"); + printf(" outFile : output file name\n"); + printf("\n"); + printf(" Example: %s -1 0 '\\ls -1 *001*.bin' (no event build, no trace, no verbose)\n", argv[0]); + printf(" %s 100 0 '\\ls -1 *001*.bin' (event build with 100 ns, no trace, no verbose)\n", argv[0]); + printf("\n\n"); + + return 1; + } + + unsigned int runStartTime = getTime_us(); + + ///============= read input + long timeWindow = atoi(argv[1]); + bool traceOn = atoi(argv[2]); + TString outFileName = argv[3]; + const int nFile = argc - NMINARG + 1; + TString inFileName[nFile]; + for( int i = 0 ; i < nFile ; i++){ inFileName[i] = argv[i + NMINARG -1];} + + /// Form outFileName; + // TString outFileName = inFileName[0]; + // int pos = outFileName.Last('/'); + // pos = outFileName.Index("_", pos+1); // find next "_" + // pos = outFileName.Index("_", pos+1); // find next "_" + // if( nFile == 1 ) pos = outFileName.Index("_", pos+1); // find next "_", S/N + // outFileName.Remove(pos); // remove the rest + // outFileName += "_" + ( timeWindow >= 0 ? std::to_string(timeWindow) : "single"); + // outFileName += ".root"; + + printf("-------> Out file name : %s \n", outFileName.Data()); + printf("=========================================\n"); + printf(" Time Window = %ld ns = %.1f us\n", timeWindow, timeWindow/1000.); + printf(" Include Trace = %s\n", traceOn ? "Yes" : "No"); + printf(" Max multiplity = %d hits/event (hard coded)\n", MAX_MULTI); + if( traceOn ) printf(" Max Trace Length = %d (hard coded)\n", MAX_TRACE_LENGTH); + printf("========================================= Number of Files : %d \n", nFile); + + unsigned long long int totalHitCount = 0; + + BinReader reader[nFile]; + for(int i = 0; i < nFile; i++ ){ + printf(">>>>>>>> %2d | %s \n", i, inFileName[i].Data()); + reader[i].OpenFile(inFileName[i]); + reader[i].ScanNumHit(); + totalHitCount += reader[i].GetNumHit(); + } + + printf("======================= total Hit Count : %llu\n", totalHitCount); + + printf("========================================= Initializing tree...\n"); + + unsigned long long evID = 0; + unsigned int multi = 0; + unsigned short sn[MAX_MULTI] = {0}; + unsigned short ch[MAX_MULTI] = {0}; + unsigned short e[MAX_MULTI] = {0}; + unsigned short e2[MAX_MULTI] = {0}; + unsigned long long e_t[MAX_MULTI] = {0}; + unsigned short traceLength[MAX_MULTI]; + short trace[MAX_MULTI][MAX_TRACE_LENGTH]; + + TFile * outRootFile = new TFile(outFileName, "recreate"); + TTree * tree = new TTree("tree", outFileName); + tree->Branch("evID", &evID, "event_ID/l"); + tree->Branch("multi", &multi, "multi/i"); + tree->Branch("sn", sn, "sn[multi]/s"); + tree->Branch("ch", ch, "ch[multi]/s"); + tree->Branch("e", e, "e[multi]/s"); + tree->Branch("e2", e2, "e2[multi]/s"); + tree->Branch("e_t", e_t, "e_t[multi]/l"); + tree->Branch("traceLength", traceLength, "traceLength[multi]/s"); + + if( traceOn ) { + tree->Branch("trace", trace,"trace[multi][MAX_TRACE_LENGTH]/S"); + tree->GetBranch("trace")->SetCompressionSettings(205); + } + + printf("========================================= Event Building ...\n"); + + //set TimeWindow to ps; + timeWindow *= 1000; + + // record the first time stamp and last time stamp + unsigned long long tStart = 0; + unsigned long long tEnd = 0; + + unsigned long long t0 = -1; + short g0 = 0 ; + int nFileFinished = 0; + multi = 0; + evID = 0; + + std::vector events; + long long ID[nFile]; // filled hit ID + for( int i = 0 ; i < nFile ; i++ ) { + reader[i].ReadBlock(); + ID[i] = -1; + } + + unsigned long long hitProcessed = 0; + + do{ + + if( debug ) printf("################################ ev build %llu \n", evID); + events.clear(); + + // //find earliest time group; + t0 = -1; + for( short i = 0; i < nFile; i++){ + if( debug ) printf("NNNN %d | ID: %lld, %lld, %lld \n", i, ID[i], reader[i].GetHitID(), reader[i].GetNumHit() ); + if( ID[i] + 1 >= reader[i].GetNumHit()) continue; + // if( ID[i] >= reader[i].GetHitID() ) reader[i].ReadBlock(); + if( debug ) reader[i].data.Print(); + if( reader[i].data.TimeStamp < t0 ) { + t0 = reader[i].data.TimeStamp; + g0 = i; + } + } + + if( evID == 0 ) tStart = t0; + if( debug ) printf("First timestamp is %llu, file ID : %u\n", t0, g0); + + for( short i = 0; i < nFile; i++){ + short ig = (i + g0 ) % nFile; + + if( ID[i] + 1 >= reader[ig].GetNumHit() ) continue; + + if( timeWindow >= 0 ){ + do{ + if( (long int)( reader[ig].data.TimeStamp - t0) <= timeWindow ){ + events.push_back(reader[ig].data); + ID[ig] ++; + }else{ + break; + } + }while( reader[ig].ReadBlock() == 1 ); + }else{ + events.push_back(reader[ig].data); + ID[ig] ++; + reader[ig].ReadBlock(); + } + + if( timeWindow < 0) break; + } + + if( events.size() > 1 ){ + std::sort(events.begin(), events.end(), [](const Data& a, const Data& b) { + return a.TimeStamp < b.TimeStamp; + }); + } + + tEnd = events.back().TimeStamp; + + hitProcessed += events.size(); + if( hitProcessed % (traceOn ? 10000 : 10000) == 0 ) printf("hit Porcessed %llu/%llu hit....%.2f%%\n\033[A\r", hitProcessed, totalHitCount, hitProcessed*100./totalHitCount); + + multi = events.size() ; + if( events.size() >= MAX_MULTI ) { + printf("\033[31m event %lld has size = %d > MAX_MULTI = %d \033[0m\n", evID, multi, MAX_MULTI); + multi = MAX_MULTI; + } + if( debug ) printf("=================================== filling data | %u \n", multi); + + for( size_t p = 0; p < multi ; p ++ ) { + if( debug ) {printf("%4zu | ", p); events[p].Print();} + + sn[p] = events[p].BoardID; + ch[p] = events[p].Channel; + e[p] = events[p].Energy; + e2[p] = events[p].Energy_short; + e_t[p] = events[p].TimeStamp; + + traceLength[p] = events[p].NSample; + if( traceOn ){ + if( traceLength[p] > MAX_TRACE_LENGTH ) { + printf("\033[31m event %lld has trace length = %d > MAX_TRACE_LENGTH = %d \033[0m\n", evID, traceLength[p], MAX_TRACE_LENGTH); + traceLength[p] = MAX_TRACE_LENGTH; + } + + for( int hh = 0; hh < traceLength[p]; hh++){ + trace[p][hh] = events[p].Trace[hh]; + } + } + } + + outRootFile->cd(); + tree->Fill(); + // tree->Write(); + + multi = 0; + evID ++; + + nFileFinished = 0; + for( int i = 0; i < nFile; i++ ){ + // printf(" %d | %lld %lld \n", i, ID[i], reader[i].GetNumHit() ); + if( ID[i] + 1 >= reader[i].GetNumHit() ) nFileFinished ++ ; + } + + if( debug ) printf(" >>>> nFileFinished : %d \n", nFileFinished); + + if( events.size() == 0 ) break; + + }while( nFileFinished < nFile ); + + tree->Write(); + + unsigned int runEndTime = getTime_us(); + double runTime = (runEndTime - runStartTime) * 1e-6; + printf("######################################### finished.\n"); + printf(" event building time = %.2f sec = %.2f min\n", runTime, runTime/60.); + // printf(" total events built = %llu by event builder (%llu in tree)\n", evID, tree->GetEntriesFast()); + printf(" total hit processed = %llu\n", hitProcessed); + printf(" total events built = %llu by event builder\n", evID); + double tDuration_sec = (tEnd - tStart) * 1e-12; + printf(" first timestamp = %20llu ps\n", tStart); + printf(" last timestamp = %20llu ps\n", tEnd); + printf(" total data duration = %.2f sec = %.2f min\n", tDuration_sec, tDuration_sec/60.); + printf("========================================> saved to %s \n", outFileName.Data()); + + TMacro info; + info.AddLine(Form("tStart= %20llu ns",tStart)); + info.AddLine(Form(" tEnd= %20llu ns",tEnd)); + info.Write("info"); + outRootFile->Close(); + + return 0; + +} \ No newline at end of file diff --git a/BinReader.h b/BinReader.h index e7669b1..e7a8ea9 100644 --- a/BinReader.h +++ b/BinReader.h @@ -44,7 +44,11 @@ struct Data{ printf("header : 0x%X \n", Header); printf(" Board : %u , Channel : %u\n", BoardID, Channel); - printf("Energy : %u , TimeStamp : %lu ps\n", Energy, TimeStamp); + if( Header & 4 ) { + printf("Energy : %u, Energy2 : %u, TimeStamp : %lu ps\n", Energy, Energy_short, TimeStamp); + }else{ + printf("Energy : %u, TimeStamp : %lu ps\n", Energy, TimeStamp); + } printf(" Flag : 0x%X\n", Flags); if( (Header & 0x8 ) >= 1 ){ /// is waevform exist printf(" Wave form code : %d , nSample : %d\n", WaveformCode, NSample); @@ -68,8 +72,8 @@ class BinReader{ long int inFilePos; bool endOfFile; bool isOpened; - Long64_t blockID; - long int nBlock; + Long64_t hitID; + long int numHit; TBenchmark gClock; @@ -91,15 +95,15 @@ class BinReader{ void UpdateFileSize(); bool IsEndOfFile(); - bool IsOpen() {return isOpened;} - long int GetFilePos() {return inFilePos;} - long int GetFileSize() {return inFileSize;} - Long64_t GetBlockID() {return blockID;} - Long64_t GetNumberOfBlock() {return nBlock;} + bool IsOpen() const {return isOpened;} + long int GetFilePos() const {return inFilePos;} + long int GetFileSize() const {return inFileSize;} + Long64_t GetHitID() const {return hitID;} + Long64_t GetNumHit() const {return numHit;} int ReadBlock(int skipTrace = 0); /// 0 = default, fill waveform if any. slow /// 1 = no fill waveform, fast - void ScanNumberOfBlock(); + void ScanNumHit(); void JumptoPrecent(int precent); ///this is offset by 1 block void PrintStatus(int mod); @@ -113,8 +117,8 @@ BinReader::BinReader(){ inFileSize = 0; inFilePos = 0; - nBlock = 0; - blockID = -1; + numHit = 0; + hitID = -1; endOfFile = false; isOpened = false; @@ -133,8 +137,8 @@ BinReader::BinReader(TString inFileName){ inFileSize = 0; inFilePos = 0; - nBlock = 0; - blockID = -1; + numHit = 0; + hitID = -1; endOfFile = false; isOpened = false; @@ -180,8 +184,8 @@ void BinReader::CloseFile(){ data.Clear(); inFileSize = 0; inFilePos = 0; - nBlock = 0; - blockID = -1; + numHit = 0; + hitID = -1; endOfFile = false; }; @@ -193,12 +197,13 @@ void BinReader::UpdateFileSize(){ } bool BinReader::IsEndOfFile() { - int haha = feof(inFile); - return haha > 0 ? true: false; + if( endOfFile ) return true; + return feof(inFile) > 0 ? true: false; } template int BinReader::FillData(T * dataItem){ if ( fread(dataItem, sizeof(*dataItem), 1, inFile) != 1 ) { + printf("!!!!! problem for reading data\n"); endOfFile = IsEndOfFile(); return -1; } @@ -238,7 +243,7 @@ int BinReader::ReadBlock(int skipTrace){ for( int i = 0; i < data.NSample; i++ ){ uint16_t haha; - fread(&haha, 2, 1, inFile); + size_t dummy = fread(&haha, 2, 1, inFile); data.Trace.push_back(haha); } @@ -247,37 +252,37 @@ int BinReader::ReadBlock(int skipTrace){ } } - blockID ++; + hitID ++; inFilePos = ftell(inFile); if( inFilePos >= inFileSize ) endOfFile = true; return 1; } -void BinReader::ScanNumberOfBlock(){ +void BinReader::ScanNumHit(){ - nBlock = 0; + numHit = 0; int count = 0; while( ReadBlock(1) != -1 ){ - nBlock ++; + numHit ++; int haha = (inFilePos*10/inFileSize)%10; if( haha == count ) { inFilePosPrecent[count] = inFilePos; - blockIDPrecent[count] = blockID; + blockIDPrecent[count] = hitID; count++; } PrintStatus(10000); } + PrintStatus(1); printf("\n\n\n"); - printf("scan complete: number of data Block : %ld\n", nBlock); - - inFilePos = 0; - blockID = -1; + printf("scan complete: number of data Block : %ld\n", numHit); rewind(inFile); ///back to the File begining - // unsigned short dummy; - // FillData(&dummy); + FillData(&data.Header); + inFilePos = 0; + hitID = -1; + endOfFile = false; } @@ -289,19 +294,19 @@ void BinReader::JumptoPrecent(int precent){ } fseek(inFile, inFilePosPrecent[precent], SEEK_SET); - blockID = blockIDPrecent[precent]; + hitID = blockIDPrecent[precent]; } void BinReader::PrintStatus(int mod){ ///==== event stats, print status every 10000 events - if ( blockID % mod == 0 ) { + if ( hitID % mod == 0 ) { UpdateFileSize(); gClock.Stop("timer"); double time = gClock.GetRealTime("timer"); gClock.Start("timer"); - printf("Total measurements: \x1B[32m%llu \x1B[0m\nReading Pos: \x1B[32m %.3f/%.3f GB\x1B[0m\nTime used:%3.0f min %5.2f sec\033[A\033[A\r", - blockID, inFilePos/(1024.*1024.*1024.), inFileSize/1024./1024./1024, TMath::Floor(time/60.), time - TMath::Floor(time/60.)*60.); + printf("Hit ID: \x1B[32m%llu \x1B[0m\nReading Pos: \x1B[32m %.3f/%.3f GB\x1B[0m\nTime used:%3.0f min %5.2f sec\033[A\033[A\r", + hitID, inFilePos/(1024.*1024.*1024.), inFileSize/1024./1024./1024, TMath::Floor(time/60.), time - TMath::Floor(time/60.)*60.); } } diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1aec35d --- /dev/null +++ b/Makefile @@ -0,0 +1,24 @@ +######################################################################## +# +# +######################################################################### + +CC = g++ + +COPTS = -fPIC -DLINUX -O2 -std=c++17 -lpthread +# COPTS = -fPIC -DLINUX -g -O0 -Wall -std=c++17 -lpthread + +ROOTLIBS = `root-config --cflags --glibs` + +ALL = Bin2Root + +######################################################################### + +all : $(ALL) + +clean : + /bin/rm -f $(OBJS) $(ALL) + +Bin2Root : Bin2Root.cpp BinReader.h + @echo "--------- making Bin2Root" + $(CC) $(COPTS) -o Bin2Root Bin2Root.cpp BinReader.h $(ROOTLIBS) diff --git a/test.C b/test.C index 32c6634..965ba8c 100644 --- a/test.C +++ b/test.C @@ -6,6 +6,9 @@ ***************************************/ #include "BinReader.h" +#include "TH1.h" +#include "TStyle.h" +#include "TCanvas.h" #define NChannel 16 @@ -13,46 +16,64 @@ TH1I * hBoard; TH1I * hChannel; TH1I * he[NChannel]; -BinReader * reader = new BinReader("DataR_run_pulser_3.BIN"); +// BinReader * reader = new BinReader("/home/ryan/ExpData/fsu_testing/testing_014_single.bin"); +BinReader * reader = new BinReader("data/run_123/UNFILTERED/Data_CH9@V1725S_19555_run_123.BIN"); void test(){ - reader->ScanNumberOfBlock(); + // reader->ReadBlock(); + // reader->data.Print(); - printf("################## Number of data Block : %llu \n", reader->GetNumberOfBlock()); + reader->ScanNumHit(); - hBoard = new TH1I ("hBoard", "BoardID", 100, 0, 10); - hChannel = new TH1I ("hChannel", "Channel", NChannel, 0, NChannel); - for( int i = 0 ; i < NChannel ; i++){ - he[i] = new TH1I(Form("he%0d", i), Form("he%0d", i), 500, 0, 10000); - } - - for( int i = 0; i < reader->GetNumberOfBlock(); i++){ + printf("################## Number of data Block : %llu \n", reader->GetNumHit()); + + unsigned int count = 0; + do{ reader->ReadBlock(); - hBoard->Fill( reader->data.BoardID ); - unsigned short ch = reader->data.Channel; - hChannel->Fill( ch); - he[ch]->Fill( reader->data.Energy); + reader->data.Print(); + count ++; + + }while( !reader->IsEndOfFile() ); + + printf(">>>>>>>>>>>>>>. count : %ld\n", count); + + reader->PrintStatus(1); + printf("\n\n\n"); + + +// hBoard = new TH1I ("hBoard", "BoardID", 100, 0, 10); +// hChannel = new TH1I ("hChannel", "Channel", NChannel, 0, NChannel); +// for( int i = 0 ; i < NChannel ; i++){ +// he[i] = new TH1I(Form("he%0d", i), Form("he%0d", i), 500, 0, 10000); +// } + +// for( int i = 0; i < reader->GetNumberOfBlock(); i++){ +// reader->ReadBlock(); +// hBoard->Fill( reader->data.BoardID ); +// unsigned short ch = reader->data.Channel; +// hChannel->Fill( ch); +// he[ch]->Fill( reader->data.Energy); - if( i < 10 ) reader->data.Print(); +// if( i < 10 ) reader->data.Print(); - if( i % 5000000 == 0 ) { - printf("------- %d \n", i); - reader->data.Print(); - } - } +// if( i % 5000000 == 0 ) { +// printf("------- %d \n", i); +// reader->data.Print(); +// } +// } - gStyle->SetOptStat("neiou"); +// gStyle->SetOptStat("neiou"); - TCanvas * haha = new TCanvas("haha", "haha", 4*400, 5*400); - haha->Divide(4,5); +// TCanvas * haha = new TCanvas("haha", "haha", 4*400, 5*400); +// haha->Divide(4,5); - haha->cd(1); hBoard->Draw(); - haha->cd(2); hChannel->Draw(); +// haha->cd(1); hBoard->Draw(); +// haha->cd(2); hChannel->Draw(); - for( int i = 0; i < 16; i++){ - haha->cd(i+5); - he[i]->Draw(); - } +// for( int i = 0; i < 16; i++){ +// haha->cd(i+5); +// he[i]->Draw(); +// } }