diff --git a/Bin2Root2.cpp b/Bin2Root2.cpp index 232bb9a..1e8dcbc 100644 --- a/Bin2Root2.cpp +++ b/Bin2Root2.cpp @@ -53,8 +53,6 @@ std::vector> findDataFiles(const std::string& patter for (const auto& entry : std::filesystem::directory_iterator(".")) { if (entry.is_regular_file()) { std::string filename = entry.path().filename().string(); - - printf("%s\n", filename.c_str()); std::smatch match; // Check for pattern DataR_run_34_YYY.BIN @@ -76,6 +74,108 @@ std::vector> findDataFiles(const std::string& patter return results; } + +std::vector hitList_A ; +std::vector hitList_B ; +BinReader * reader = nullptr; + +int ReadBatch(int bufferSize){ + + if( hitList_A.size() == 0 ){ + for( int i = 0 ; i < bufferSize; i++ ){ + if( reader->ReadBlock() != 1 ){ + break; + } + //<<< should apply time offset here + hitList_A.push_back(reader->data); + } + if( hitList_A.size() > 1){ + std::sort(hitList_A.begin(), hitList_A.end(), [](const Data& a, const Data& b) { + return a.TimeStamp < b.TimeStamp; + }); + } + }else{ + hitList_A.clear(); + hitList_A = hitList_B; + } + + //reader next batch + hitList_B.clear(); + for( int i = 0 ; i < bufferSize; i++ ){ + if( reader->ReadBlock() != 1 ){ + break; + } + //<<< should apply time offset here + hitList_B.push_back(reader->data); + } + if( hitList_B.size() > 1 ){ + std::sort(hitList_B.begin(), hitList_B.end(), [](const Data& a, const Data& b) { + return a.TimeStamp < b.TimeStamp; + }); + } + + if( hitList_B.size() == 0 ) return 1; + + uint64_t t0_A = hitList_A.front().TimeStamp; + uint64_t t1_A = hitList_A.back().TimeStamp; + uint64_t t0_B = hitList_B.front().TimeStamp; + + if( t0_A >= t0_B ){ + printf("need to increase the batch size\n"); + printf("t0_A : %15lu | %zu\n", t0_A, hitList_A.size()); + printf("t0_B : %15lu | %zu\n", t0_B, hitList_B.size()); + return -1; + } + + if( t1_A >= t0_B ){ // move the overlap part to hitsLis_A; + + ulong ID_A = 0; + ulong ID_B = 0; + std::vector hitTemp; + + // find the hit that is >= t0_B, save them to hitTemp + for( size_t j = 0; j < hitList_A.size() ; j++){ + if( hitList_A[j].TimeStamp < t0_B ) continue;; + if( ID_A == 0 ) ID_A = j; + hitTemp.push_back(hitList_A[j]); + } + + // remove hitList_A element that is >= t0_B + hitList_A.erase(hitList_A.begin() + ID_A, hitList_A.end() ); + + // find the hit that is <= t1_A, save them to hitTemp + for( size_t j = 0; j < hitList_B.size(); j++){ + if( hitList_B[j].TimeStamp > t1_A ) { + break; + } + hitTemp.push_back(hitList_B[j]); + ID_B = j + 1; + } + + // remove hit elements that is <= t1_A + hitList_B.erase(hitList_B.begin(), hitList_B.begin() + ID_B ); + + // sort hitTemp + std::sort(hitTemp.begin(), hitTemp.end(), [](const Data& a, const Data& b) { + return a.TimeStamp < b.TimeStamp; + }); + + //push back the hitList_A + for( size_t j = 0; j < hitTemp.size(); j++){ + hitList_A.push_back(hitTemp[j]); + } + + } + + // printf("\n"); + // printf("hitList A : %zu\n", hitList_A.size()); + // printf("hitList B : %zu\n", hitList_B.size()); + + return 1; + +} + + //^############################################################# //^############################################################# int main(int argc, char **argv) { @@ -87,7 +187,6 @@ int main(int argc, char **argv) { printf("Incorrect number of arguments:\n"); printf("%s [timeWindow] [RunNum] \n", argv[0]); printf(" timeWindow : in ns, -1 = no event building \n"); - printf(" time Offset File : 0 for nothing \n"); printf("\n\n"); return 1; @@ -95,8 +194,10 @@ int main(int argc, char **argv) { unsigned int runStartTime = getTime_us(); + int bufferSize = 5000000; + ///============= read input - long timeWindow = atoi(argv[1]); + long timeWindow = atoi(argv[1]); // ns short runNum = atoi(argv[2]); ///============ time offset @@ -112,40 +213,36 @@ int main(int argc, char **argv) { std::vector> inFileName = findDataFiles(pattern); int nFile = inFileName.size(); - printf("-------> Out file name : %s \n", outFileName.Data()); printf("=========================================\n"); printf(" Time Window = %ld ns = %.1f us\n", timeWindow, timeWindow/1000.); printf(" Max multiplity = %d hits/event (hard coded)\n", MAX_MULTI); - printf("========================================= Number of Files : %d \n", nFile); - + printf(" Out file name = %s \n", outFileName.Data()); + printf(" Buffer Size = %d\n", bufferSize); + printf("=============================== Number of input Files : %d \n", nFile); for( int i = 0 ; i < nFile; i++ ){ printf(" %3d | %s\n", i, inFileName[i].second.c_str()); } - - return 0; - - /* - - 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], 0, true); - // if( timeOffsetList.size() > 1 ){ - // for (size_t i = 1 ; timeOffsetList.size(); i++) { - // int sn = extractDigiSN(inFileName[i].Data(), timeOffsetList[0].first); - // if( sn == timeOffsetList[i].first ) reader[i].SetTimeOffset(timeOffsetList[i].second); - // } - // } - reader[i].ScanNumHit(); - totalHitCount += reader[i].GetNumHit(); + printf("========================================= Scanning files\n"); + unsigned long long totalHitCount = 0; + uint16_t tempHeader; + for( int i = 0; i < nFile; i++){ + BinReader tempReader; + if( i == 0 ) { + tempReader.OpenFile(inFileName[i].second); + tempHeader = tempReader.data.Header; + }else{ + tempReader.OpenFile(inFileName[i].second, 0, true); + tempReader.SetCustomHeader(tempHeader); + } + tempReader.ScanNumHit(); + totalHitCount += tempReader.GetNumHit(); } - printf("======================= total Hit Count : %llu\n", totalHitCount); + printf("============================ total Num. of Hit : %llu\n", totalHitCount); + + timeWindow *= 1000; // to ps printf("========================================= Initializing tree...\n"); - unsigned long long evID = 0; unsigned int multi = 0; unsigned short sn[MAX_MULTI] = {0}; @@ -154,8 +251,8 @@ int main(int argc, char **argv) { // unsigned short e2[MAX_MULTI] = {0}; unsigned long long e_t[MAX_MULTI] = {0}; // unsigned short e_f[MAX_MULTI] = {0}; - unsigned short traceLength[MAX_MULTI]; - short trace[MAX_MULTI][MAX_TRACE_LENGTH]; + // unsigned short traceLength[MAX_MULTI]; + // short trace[MAX_MULTI][MAX_TRACE_LENGTH]; TFile * outRootFile = new TFile(outFileName, "recreate"); TTree * tree = new TTree("tree", outFileName); @@ -165,152 +262,104 @@ int main(int argc, char **argv) { 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("e_f", e_f, "e_f[multi]/s"); - tree->Branch("traceLength", traceLength, "traceLength[multi]/s"); - - if( traceOn ) { - tree->Branch("trace", trace,"trace[multi][MAX_TRACE_LENGTH]/S"); - tree->GetBranch("trace")->SetCompressionSettings(205); - } + tree->Branch("e_t", e_t, "e_t[multi]/l"); - 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(); - SetTimeOffset(&reader[i], timeOffsetList); - ID[i] = -1; - } - unsigned long long hitProcessed = 0; + printf("========================================= Read File & events building...\n"); + ///=========================== Read file + reader = new BinReader(); + int fileID = 0; + reader->OpenFile(inFileName[fileID].second); + const uint16_t header = reader->data.Header; + + int ret = 0; + uint64_t t0 = -1; + + std::vector event; + 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("NNNNNNNNNNNNNNN %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++){ - - if( ID[i] + 1 >= reader[i].GetNumHit() ) continue; - - if( timeWindow >= 0 ){ - int ret = 0; - do{ - if( (long int)( reader[i].data.TimeStamp - t0) <= timeWindow ){ - events.push_back(reader[i].data); - ID[i] ++; - }else{ - break; - } - ret = reader[i].ReadBlock(); - SetTimeOffset(&reader[i], timeOffsetList); - }while( ret == 1 ); + if( reader->IsEndOfFile() ){ + reader->CloseFile(); + fileID++; + if( fileID < nFile ) { + printf("\n========= Open next file.\n"); + reader->OpenFile(inFileName[fileID].second, 0, true); + reader->SetCustomHeader(header); }else{ - events.push_back(reader[g0].data); - ID[g0] ++; - reader[g0].ReadBlock(); - SetTimeOffset(&reader[g0], timeOffsetList); - break; - } - - //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); - // for( int k = 0 ; k < multi; k++){ - // printf("%d | %d %2d %llu | %llu , %llu , %llu\n", k, events[k].BoardID, events[k].Channel, events[k].TimeStamp, (long int)( events[k].TimeStamp - t0), t0, timeWindow); - // } - 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 / 1000; - // e_f[p] = events[p].TimeStamp % 1000; - - 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]; - } + printf("\n========= no more file.\n"); + // break; } } + ret = ReadBatch(bufferSize); + if( tStart == 0 ) tStart = hitList_A[0].TimeStamp; + tEnd = hitList_A.back().TimeStamp; - outRootFile->cd(); - tree->Fill(); - // tree->Write(); + //build event from hitList_A; + for( size_t i = 0; i < hitList_A.size(); i++){ - multi = 0; - evID ++; + if( timeWindow < 0 ){ + + multi = 1; + sn[0] = hitList_A[i].BoardID; + ch[0] = hitList_A[i].Channel; + e[0] = hitList_A[i].Energy; + // e2[p] = hitList_A[i].Energy_short; + e_t[0] = hitList_A[i].TimeStamp / 1000; + tree->Fill(); + evID ++; + + }else{ + + if( t0 == -1 ) { + t0 = hitList_A[i].TimeStamp; + event.push_back(hitList_A[i]); + } + + if( hitList_A[i].TimeStamp - t0 < timeWindow ){ + event.push_back(hitList_A[i]); + }else{ + + //fill an event + multi = event.size(); + if( multi > MAX_MULTI ){ + printf("\033[31m event %lld has size = %d > MAX_MULTI = %d \033[0m\n", evID, multi, MAX_MULTI); + // for( int k = 0 ; k < multi; k++){ + // printf("%d | %d %2d %llu | %llu , %llu , %llu\n", k, events[k].BoardID, events[k].Channel, events[k].TimeStamp, (long int)( events[k].TimeStamp - t0), t0, timeWindow); + // } + multi = MAX_MULTI; + } + + for( size_t p = 0; p < multi ; p ++ ) { + sn[p] = event[p].BoardID; + ch[p] = event[p].Channel; + e[p] = event[p].Energy; + // e2[p] = event[p].Energy_short; + e_t[p] = event[p].TimeStamp / 1000; + } + tree->Fill(); + evID ++; + + // start a new event + event.clear(); + t0 = hitList_A[i].TimeStamp; + event.push_back(hitList_A[i]); + + } + } + hitProcessed ++; + if( hitProcessed % 10000 == 0 ) printf("hit Porcessed %llu/%llu hit....%.2f%%\n\033[A\r", hitProcessed, totalHitCount, hitProcessed*100./totalHitCount); - 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; - - if( debug > 1 && hitProcessed > debug ) break; - - }while( nFileFinished < nFile ); + tree->Write(); + if( fileID >= nFile ) break; + }while(ret == 1); tree->Write(); @@ -318,9 +367,8 @@ int main(int argc, char **argv) { 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 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); @@ -333,6 +381,8 @@ int main(int argc, char **argv) { info.Write("info"); outRootFile->Close(); + delete reader; + return 0; - */ + } diff --git a/BinReader.h b/BinReader.h index 7de6755..57ea352 100644 --- a/BinReader.h +++ b/BinReader.h @@ -94,6 +94,7 @@ class BinReader{ ~BinReader(); void OpenFile(TString inFileName, int64_t timeOffset = 0, bool noHeader = false); + void SetCustomHeader(uint16_t Header); // void SetDataFormat(bool has ); void CloseFile(); void UpdateFileSize(); @@ -112,7 +113,7 @@ class BinReader{ void PrintStatus(int mod); void SetTimeOffset(int64_t timeOffset) { this->timeOffset = timeOffset; } - + }; //========================== implementation @@ -135,7 +136,7 @@ BinReader::BinReader(){ } BinReader::~BinReader(){ - fclose(inFile); /// fclose already delete inFile; + if( inFile ) fclose(inFile); /// fclose already delete inFile; } BinReader::BinReader(TString inFileName, int64_t timeOffset, bool noHeader){ @@ -167,6 +168,11 @@ void BinReader::OpenFile(TString inFileName, int64_t timeOffset, bool noHeader){ gClock.Start("timer"); isOpened = true; + + // normal format: isHeaderOK = true, isNoHeaderFormat= false, isOldFormat = false + // old format: isHeaderOK = true, isNoHeaderFormat= false, isOldFormat = true + //no header format: isHeaderOK = false, isNoHeaderFormat= true, isOldFormat = false + if( noHeader ){ data.Header = 0x0; @@ -207,8 +213,14 @@ void BinReader::OpenFile(TString inFileName, int64_t timeOffset, bool noHeader){ } }; +void BinReader::SetCustomHeader(uint16_t Header){ + data.Header = Header; + isHeaderOK = true; +} + void BinReader::CloseFile(){ - fclose(inFile); + if(inFile) fclose(inFile); + inFile = nullptr; isOpened = false; data.Clear(); inFileSize = 0; @@ -227,6 +239,7 @@ void BinReader::UpdateFileSize(){ bool BinReader::IsEndOfFile() { if( endOfFile ) return true; + if( inFile == nullptr ) return true; return feof(inFile) > 0 ? true: false; } @@ -245,8 +258,7 @@ int BinReader::ReadBlock(int skipTrace){ if( feof(inFile) ) return -1; if( endOfFile ) return -1; - - if( isNoHeaderFormat ) { + if( isNoHeaderFormat && data.Header == 0x0 ) { FillData(&data.BoardID); FillData(&data.Channel); FillData(&data.TimeStamp); @@ -332,7 +344,7 @@ void BinReader::ScanNumHit(){ printf("scan complete: number of data Block : %ld\n", numHit); rewind(inFile); ///back to the File begining - if( !isOldFormat && isHeaderOK ){ + if( isOldFormat == false && isNoHeaderFormat == false ){ // only when normal format FillData(&data.Header); } inFilePos = 0; @@ -365,5 +377,4 @@ void BinReader::PrintStatus(int mod){ } - #endif