#include "MultiBuilder.h" #include MultiBuilder::MultiBuilder(Data ** multiData, std::vector type, std::vector sn) : nData(type.size()){ DebugPrint("%s", "MultiBuilder"); data = multiData; typeList = type; snList = sn; numTotCh = 0; for( uShort i = 0; i < nData; i++) { idList.push_back(i); dataSize.push_back(data[i]->GetDataSize()); numTotCh += data[i]->GetNChannel(); } timeWindow = 100; leftOverTime = 100; breakTime = -1; timeJump = 1e8; lastEventTime = 0; forceStop = false; ClearEvents(); // for( int i = 0; i < nData; i++){ // printf("sn: %d, numCh : %d \n", snList[i], data[i]->GetNChannel()); // } } MultiBuilder::MultiBuilder(Data * singleData, int type, int sn): nData(1){ DebugPrint("%s", "MultiBuilder"); data = new Data *[1]; data[0] = singleData; numTotCh = data[0]->GetNChannel(); typeList.push_back(type); snList.push_back(sn); idList.push_back(0); timeWindow = 100; leftOverTime = 100; breakTime = -1; timeJump = 1e8; lastEventTime = 0; forceStop = false; ClearEvents(); } MultiBuilder::~MultiBuilder(){ DebugPrint("%s", "MultiBuilder"); } void MultiBuilder::ClearEvents(){ DebugPrint("%s", "MultiBuilder"); eventIndex = -1; eventBuilt = 0; totalEventBuilt = 0; for( int i = 0; i < MaxNEvent; i++) events[i].clear(); for( int i = 0; i < MaxNDigitizer; i++){ for( int j = 0; j < MaxNChannels; j++){ loopIndex[i][j] = 0; nextIndex[i][j] = -1; chExhaused[i][j] = false; lastBackWardIndex[i][j] = 0; } earlistDigi = -1; earlistCh = -1; earlistTime = -1; latestTime = 0; nExhaushedCh = 0; } } void MultiBuilder::PrintStat(){ DebugPrint("%s", "MultiBuilder"); printf("Total number of evet built : %ld\n", totalEventBuilt); for( int i = 0; i < nData ; i++){ for( int ch = 0; ch < data[i]->GetNChannel() ; ch++){ if( nextIndex[i][ch] >= 0 ) printf("%d %3d %2d | %7d (%d)\n", i, snList[i], ch, nextIndex[i][ch], loopIndex[i][ch]); } } } void MultiBuilder::PrintAllEvent(){ DebugPrint("%s", "MultiBuilder"); printf("Total number of evet built : %ld\n", totalEventBuilt); for( int i = 0; i < totalEventBuilt; i++){ printf("%5d ------- size: %ld\n", i, events[i].size()); for( int j = 0; j < (int)events[i].size(); j++){ events[i][j].Print(); } } } void MultiBuilder::FindEarlistTimeAndCh(bool verbose){ DebugPrint("%s", "MultiBuilder"); earlistTime = -1; earlistDigi = -1; earlistCh = -1; nExhaushedCh = 0; for( int i = 0; i < nData; i++){ for( int j = 0; j < data[i]->GetNChannel(); j++ ) { chExhaused[i][j] = false; } for(unsigned int ch = 0; ch < data[i]->GetNChannel(); ch ++){ {// check is dataIndex is valid int index = data[i]->GetDataIndex(ch); if( index < 0 ) { nExhaushedCh ++; chExhaused[i][ch] = true; continue; } if( data[i]->GetTimestamp(ch, index) == 0 || loopIndex[i][ch] * dataSize[i] > data[i]->GetLoopIndex(ch) * dataSize[i] + data[i]->GetDataIndex(ch)) { nExhaushedCh ++; chExhaused[i][ch] = true; continue; } } if( nextIndex[i][ch] == -1 ) nextIndex[i][ch] = 0; unsigned long long time = data[i]->GetTimestamp(ch, nextIndex[i][ch]); if( time < earlistTime ) { earlistTime = time; earlistDigi = i; earlistCh = ch; } // printf(" ch : %d | time %llu | %llu\n", ch, time, earlistTime); } } if( verbose ) printf("%s | bd : %d, ch : %d, %llu\n", __func__, earlistDigi, earlistCh, earlistTime); } void MultiBuilder::FindLatestTimeAndCh(bool verbose){ DebugPrint("%s", "MultiBuilder"); latestTime = 0; latestDigi = -1; latestCh = -1; nExhaushedCh = 0; for( int i = 0; i < nData; i++){ for( int j = 0; j < data[i]->GetNChannel(); j++ ) chExhaused[i][j] = false; for(unsigned int ch = 0; ch < data[i]->GetNChannel(); ch ++){ if( nextIndex[i][ch] < 0 || data[i]->GetDataIndex(ch) < 0 || nextIndex[i][ch] <= lastBackWardIndex[i][ch] ) { nExhaushedCh ++; chExhaused[i][ch] = true; // printf(", exhanshed. %d \n", nExhaushedCh); continue; } unsigned long long time = data[i]->GetTimestamp(ch, nextIndex[i][ch]); // printf(", time : %llu\n", time ); if( time > latestTime ) { latestTime = time; latestDigi = i; latestCh = ch; } } } if( verbose ) printf("%s | bd : %d, ch : %d, %llu\n", __func__, latestDigi, latestCh, latestTime); } void MultiBuilder::FindEarlistTimeAmongLastData(bool verbose){ DebugPrint("%s", "MultiBuilder"); latestTime = -1; latestCh = -1; latestDigi = -1; for( int i = 0; i < nData; i++){ for( unsigned ch = 0; ch < data[i]->GetNChannel(); ch++ ){ if( chExhaused[i][ch] ) continue; int index = data[i]->GetDataIndex(ch); if( index == -1 ) continue; if( data[i]->GetTimestamp(ch, index) < latestTime ) { latestTime = data[i]->GetTimestamp(ch, index); latestCh = ch; latestDigi = i; } } } if( verbose ) printf("%s | bd : %d, ch : %d, %lld \n", __func__, latestDigi, latestCh, latestTime); } void MultiBuilder::FindLatestTimeOfData(bool verbose){ DebugPrint("%s", "MultiBuilder"); latestTime = 0; latestCh = -1; latestDigi = -1; for( int i = 0; i < nData; i++){ // printf("%s | digi-%d-th | %d\n", __func__, i, data[i]->GetNChannel()); for( unsigned ch = 0; ch < data[i]->GetNChannel(); ch++ ){ int index = data[i]->GetDataIndex(ch); // printf("ch-%2d | index : %d \n", ch, index); if( index == -1 ) continue; if( data[i]->GetTimestamp(ch, index) > latestTime ) { latestTime = data[i]->GetTimestamp(ch, index); latestCh = ch; latestDigi = i; } } } if( verbose ) printf("%s | bd : %d, ch : %d, %lld \n", __func__, latestDigi, latestCh, latestTime); } void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){ DebugPrint("%s", "MultiBuilder"); FindEarlistTimeAmongLastData(verbose); // give lastest Time, Ch, and Digi for event building FindEarlistTimeAndCh(verbose); //Give the earliest time, ch, digi if( earlistCh == -1 || nExhaushedCh == nData * MaxNChannels) return; /// no data eventBuilt = 0; //======= Start building event Hit em; do{ if( forceStop ) break; eventIndex ++; if( eventIndex >= MaxNEvent ) eventIndex = 0; events[eventIndex].clear(); em.Clear(); for( int k = 0; k < nData; k++){ int bd = (k + earlistDigi) % nData; // printf("##### %d/%d | ", k, nData); // data[k]->PrintAllData(true, 10); const int numCh = data[bd]->GetNChannel(); for( int i = 0; i < numCh; i++){ int ch = (i + earlistCh ) % numCh; // printf("ch : %d | exhaused ? %s \n", ch, chExhaused[bd][ch] ? "Yes" : "No"); if( chExhaused[bd][ch] ) continue; if( loopIndex[bd][ch] * dataSize[bd] + nextIndex[bd][ch] > data[bd]->GetLoopIndex(ch) * dataSize[bd] + data[bd]->GetDataIndex(ch)) { nExhaushedCh ++; chExhaused[bd][ch] = true; continue; } do { if ( nextIndex[bd][ch] < 0 ) break; // hotfix unsigned long long time = data[bd]->GetTimestamp(ch, nextIndex[bd][ch]); //printf("%6ld, sn: %5d, ch: %2d, timestamp : %16llu | earlistTime : %16llu | timeWindow : %u \n", eventIndex, data[bd]->boardSN, ch, time, earlistTime, timeWindow); if( time >= earlistTime && (time - earlistTime <= timeWindow) ){ em.sn = snList[bd]; em.ch = ch; em.energy = data[bd]->GetEnergy(ch, nextIndex[bd][ch]); em.timestamp = time; em.fineTime = data[bd]->GetFineTime(ch, nextIndex[bd][ch]); if( !skipTrace ) em.trace = data[bd]->Waveform1[ch][nextIndex[bd][ch]]; if( typeList[bd] == DPPTypeCode::DPP_PSD_CODE ) em.energy2 = data[bd]->GetEnergy2(ch, nextIndex[bd][ch]); events[eventIndex].push_back(em); nextIndex[bd][ch]++; if( nextIndex[bd][ch] >= dataSize[bd]) { loopIndex[bd][ch] ++; nextIndex[bd][ch] = 0; } }else{ break; } if( timeWindow <= 0 ) break; }while( true ); if( timeWindow <= 0 ) break; } if( timeWindow <= 0 ) break; } if( events[eventIndex].size() == 0 ) continue; if( events[eventIndex].size() > 1) { std::sort(events[eventIndex].begin(), events[eventIndex].end(), [](const Hit& a, const Hit& b) { return a.timestamp < b.timestamp; }); } lastEventTime = events[eventIndex].back().timestamp; ///Find the next earlist FindEarlistTimeAndCh(false); // //if there is a time jump, say, bigger than TimeJump. break if( earlistTime - lastEventTime > timeJump ) { if( verbose ){ printf("!!!!!!!! Time Jump detected stop event building and get more data.\n"); printf("event index : %6lu, earlist time : %16llu\n", eventIndex, earlistTime); printf(" %6s last event time : %16llu \n", "", lastEventTime); printf(" %6s time jump > %16llu \n", "", timeJump); } return; } eventBuilt ++; totalEventBuilt ++; if( verbose ){ printf(">>>>>>>>>>>>>>>>> Event ID : %ld, total built: %ld, multiplicity : %ld\n", eventIndex, totalEventBuilt, events[eventIndex].size()); for( int i = 0; i <(int) events[eventIndex].size(); i++){ int chxxx = events[eventIndex][i].ch; int sn = events[eventIndex][i].sn; int bd = 0; for( int pp = 0; pp < nData; pp++){ if( sn == data[pp]->boardSN ) { bd = pp; break; } } printf("%05d, %02d | %5d | %5d %llu \n", sn, chxxx, nextIndex[bd][chxxx], events[eventIndex][i].energy, events[eventIndex][i].timestamp); } if( nExhaushedCh == nData * MaxNChannels ) { printf("######################### no more event to be built\n"); break; } printf("----- next bd : %d, ch : %d, next earlist Time : %llu.\n", earlistDigi, earlistCh, earlistTime); //printf("leftOver %llu, breakTime %llu \n", leftOverTime, breakTime); } if( !isFinal ){ if( latestTime - earlistTime <= leftOverTime){ if( verbose ) printf("######################### left over data for next build, latesTime : %llu. | leftOverTime : %llu\n", latestTime, leftOverTime); break; } if( earlistTime > breakTime ) { if( verbose ) printf("######################### left over data for next build, earlistTime : %llu. | breakTime : %llu\n", earlistTime, breakTime); break; } } }while(nExhaushedCh < nData * MaxNChannels); forceStop = false; } void MultiBuilder::BuildEventsBackWard(int maxNumEvent, bool verbose){ DebugPrint("%s", "MultiBuilder"); //skip trace, and only build for maxNumEvent events max // Get the last data index and loop index for( int k = 0; k < nData; k++){ for( int i = 0; i < data[k]->GetNChannel(); i++){ nextIndex[k][i] = data[k]->GetDataIndex(i); loopIndex[k][i] = data[k]->GetLoopIndex(i); } } FindLatestTimeAndCh(verbose); //========== build event eventBuilt = 0; Hit em; do{ if( forceStop ) break; eventIndex ++; if( eventIndex >= MaxNEvent ) eventIndex = 0; events[eventIndex].clear(); em.Clear(); for( int k = 0; k < nData; k++){ int bd = (k + latestDigi) % nData; const int numCh = data[k]->GetNChannel(); for( int i = 0; i < numCh; i++){ int ch = (i + latestCh) % numCh; if( chExhaused[bd][ch] ) continue; if( nextIndex[bd][ch] <= lastBackWardIndex[bd][ch] || nextIndex[bd][ch] <= 0){ nExhaushedCh ++; chExhaused[bd][ch] = true; continue; } do{ unsigned long long time = data[bd]->GetTimestamp(ch, nextIndex[bd][ch]); if( time <= latestTime && (latestTime - time <= timeWindow)){ em.sn = snList[bd]; em.ch = ch; em.energy = data[bd]->GetEnergy(ch, nextIndex[bd][ch]); em.timestamp = time; if( typeList[bd] == DPPTypeCode::DPP_PSD_CODE ) em.energy2 = data[bd]->GetEnergy2(ch, nextIndex[bd][ch]); events[eventIndex].push_back(em); nextIndex[bd][ch]--; if( nextIndex[bd][ch] < 0 && data[bd]->GetLoopIndex(ch) > 0 ) nextIndex[bd][ch] = dataSize[bd] - 1; }else{ break; } if( timeWindow == 0 ) break; }while(true); if( timeWindow == 0 ) break; } if( timeWindow == 0 ) break; } FindLatestTimeAndCh(verbose); if( verbose ) printf(" nExhaushedCh %d | numToCh %d \n", nExhaushedCh, numTotCh); if( nExhaushedCh == numTotCh ) { if( verbose ) printf("######################### no more event to be built\n"); break; } if( verbose ) printf("----- next bd: %d, ch : %d, next latest Time : %llu.\n", latestDigi, latestCh, latestTime); if( events[eventIndex].size() > 0 ) { eventBuilt ++; totalEventBuilt ++; std::sort(events[eventIndex].begin(), events[eventIndex].end(), [](const Hit& a, const Hit& b) { return a.timestamp < b.timestamp; }); }else{ continue; } if( verbose ){ printf(">>>>>>>>>>>>>>>>> Event ID : %ld, total built: %ld, multiplicity : %ld\n", eventIndex, totalEventBuilt, events[eventIndex].size()); for( int i = 0; i <(int) events[eventIndex].size(); i++){ int chxxx = events[eventIndex][i].ch; int sn = events[eventIndex][i].sn; int bd = 0; for( int pp = 0; pp < nData; pp++){ if( sn == data[pp]->boardSN ) { bd = pp; break; } } printf("%5d, %02d | %5d | %5d %llu \n", sn, chxxx, nextIndex[bd][chxxx], events[eventIndex][i].energy, events[eventIndex][i].timestamp); } } }while(nExhaushedCh < numTotCh && eventBuilt < maxNumEvent); forceStop = false; // remember the end of DataIndex, prevent over build for( int k = 0; k < nData; k++){ for( int i = 0; i < data[k]->GetNChannel(); i++){ lastBackWardIndex[k][i] = data[k]->GetDataIndex(i); } } }