2024-01-12 19:12:37 -05:00
# include "fsuReader.h"
2024-01-26 15:11:20 -05:00
# include "CustomStruct.h"
2024-01-12 19:12:37 -05:00
# include "TROOT.h"
# include "TSystem.h"
# include "TClonesArray.h"
# include "TGraph.h"
# include "TFile.h"
# include "TTree.h"
2024-02-19 11:53:29 -05:00
# include "TMacro.h"
2024-01-12 19:12:37 -05:00
2024-01-22 13:56:18 -05:00
# define MAX_MULTI 1000
2024-01-12 19:12:37 -05:00
//^#############################################################
//^#############################################################
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] [verbose] [inFile1] [inFile2] .... \n " , argv [ 0 ] ) ;
printf ( " timeWindow : in ns \n " ) ;
printf ( " verbose : > 0 for debug \n " ) ;
2024-01-20 13:35:19 -05:00
printf ( " Output file name is contructed from inFile1 \n " ) ;
printf ( " \n " ) ;
printf ( " =========================== Working flow \n " ) ;
printf ( " 1) Load all data into memories as vector and sort \n " ) ;
printf ( " 2) Build event. \n " ) ;
printf ( " \n \n " ) ;
2024-01-12 19:12:37 -05:00
return 1 ;
}
2024-01-25 18:34:58 -05:00
uInt runStartTime = getTime_us ( ) ;
2024-01-12 19:12:37 -05:00
///============= read input
unsigned int timeWindow = atoi ( argv [ 1 ] ) ;
//bool traceOn = atoi(argv[3]);
unsigned int debug = atoi ( argv [ 2 ] ) ;
int nFile = argc - 3 ;
TString inFileName [ nFile ] ;
for ( int i = 0 ; i < nFile ; i + + ) {
inFileName [ i ] = argv [ i + 3 ] ;
}
/// Form outFileName;
TString outFileName = inFileName [ 0 ] ;
2024-01-24 16:18:20 -05:00
int pos = outFileName . Last ( ' / ' ) ;
2024-01-25 18:34:58 -05:00
pos = outFileName . Index ( " _ " , pos + 1 ) ; // find next "_", expName
pos = outFileName . Index ( " _ " , pos + 1 ) ; // find next "_", runID
if ( nFile = = 1 ) pos = outFileName . Index ( " _ " , pos + 1 ) ; // find next "_", S/N
2024-01-24 16:18:20 -05:00
outFileName . Remove ( pos ) ; // remove the rest
2024-01-19 19:24:51 -05:00
outFileName + = " _ " + std : : to_string ( timeWindow ) + " _noTrace " ;
2024-01-12 19:12:37 -05:00
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 ns = %.1f us \n " , timeWindow , timeWindow / 1000. ) ;
//printf(" Buffer size = %.0f event/channel\n", MaxNData * bufferSize);
printf ( " ===================================== input files: \n " ) ;
///============= sorting file by the serial number & order
2024-01-16 15:39:41 -05:00
std : : vector < FileInfo > fileInfo ;
2024-01-12 19:12:37 -05:00
FSUReader * * reader = new FSUReader * [ nFile ] ;
// file name format is expName_runID_SN_DPP_tick2ns_order.fsu
for ( int i = 0 ; i < nFile ; i + + ) {
printf ( " Processing %s (%d/%d) ..... \n \033 [A \r " , inFileName [ i ] . Data ( ) , i + 1 , nFile ) ;
2024-01-20 13:35:19 -05:00
reader [ i ] = new FSUReader ( inFileName [ i ] . Data ( ) , 600 , 0 ) ; // the 600 is expecting each agg, there are maximum 1000 hit/ch.
2024-01-20 01:01:10 -05:00
reader [ i ] - > ScanNumBlock ( 1 , 1 ) ;
2024-01-20 13:35:19 -05:00
reader [ i ] - > GetData ( ) - > ClearDataPointer ( ) ;
2024-01-12 19:12:37 -05:00
FileInfo tempInfo ;
tempInfo . fileName = inFileName [ i ] ;
tempInfo . readerID = i ;
tempInfo . SN = reader [ i ] - > GetSN ( ) ;
2024-06-19 16:55:38 -04:00
tempInfo . hitCount = reader [ i ] - > GetTotalHitCount ( ) ;
2024-01-12 19:12:37 -05:00
tempInfo . fileSize = reader [ i ] - > GetFileByteSize ( ) ;
tempInfo . tick2ns = reader [ i ] - > GetTick2ns ( ) ;
tempInfo . DPPType = reader [ i ] - > GetDPPType ( ) ;
tempInfo . order = reader [ i ] - > GetFileOrder ( ) ;
tempInfo . CalOrder ( ) ;
fileInfo . push_back ( tempInfo ) ;
}
std : : sort ( fileInfo . begin ( ) , fileInfo . end ( ) , [ ] ( const FileInfo & a , const FileInfo & b ) {
return a . ID < b . ID ;
} ) ;
unsigned int totHitCount = 0 ;
for ( int i = 0 ; i < nFile ; i + + ) {
printf ( " %d | " , i ) ;
fileInfo [ i ] . Print ( ) ;
totHitCount + = fileInfo [ i ] . hitCount ;
}
2024-01-16 15:39:41 -05:00
printf ( " ----- total number of hit : %u. \n " , totHitCount ) ;
2024-01-12 19:12:37 -05:00
//*======================================= Sort files into groups
std : : vector < GroupInfo > group ;
for ( int i = 0 ; i < nFile ; i + + ) {
2024-01-18 18:55:37 -05:00
if ( i = = 0 | | group . back ( ) . sn ! = fileInfo [ i ] . SN ) {
2024-01-12 19:12:37 -05:00
group . push_back ( GroupInfo ( ) ) ;
group . back ( ) . readerIDList . push_back ( fileInfo [ i ] . readerID ) ; // an empty struct
2024-01-16 15:39:41 -05:00
group . back ( ) . currentID = 0 ;
group . back ( ) . hitCount = fileInfo [ i ] . hitCount ;
group . back ( ) . hitID = 0 ;
group . back ( ) . sn = fileInfo [ i ] . SN ;
group . back ( ) . finished = false ;
2024-01-12 19:12:37 -05:00
} else {
group . back ( ) . readerIDList . push_back ( fileInfo [ i ] . readerID ) ;
}
}
int nGroup = group . size ( ) ;
printf ( " ===================================== number of file Group by digitizer %d. \n " , nGroup ) ;
for ( int i = 0 ; i < nGroup ; i + + ) {
2024-01-16 15:39:41 -05:00
printf ( " Digi-%d, DPPType: %d \n " , reader [ group [ i ] . readerIDList [ 0 ] ] - > GetSN ( ) , reader [ group [ i ] . readerIDList [ 0 ] ] - > GetDPPType ( ) ) ;
2024-01-12 19:12:37 -05:00
for ( int j = 0 ; j < ( int ) group [ i ] . readerIDList . size ( ) ; j + + ) {
uShort rID = group [ i ] . readerIDList [ j ] ;
printf ( " %s \n " , reader [ rID ] - > GetFileName ( ) . c_str ( ) ) ;
2024-01-20 01:01:10 -05:00
reader [ rID ] - > PrintHit ( 10 , 0 ) ;
2024-01-12 19:12:37 -05:00
}
}
// //*====================================== create tree
2024-01-16 15:39:41 -05:00
TFile * outRootFile = new TFile ( outFileName , " recreate " ) ;
TTree * tree = new TTree ( " tree " , outFileName ) ;
2024-01-20 01:44:13 -05:00
unsigned long long evID = 0 ;
2024-01-19 19:24:51 -05:00
unsigned int multi = 0 ;
2024-01-16 15:39:41 -05:00
unsigned short sn [ MAX_MULTI ] = { 0 } ; /// board SN
unsigned short ch [ MAX_MULTI ] = { 0 } ; /// chID
unsigned short e [ MAX_MULTI ] = { 0 } ; /// 15 bit
unsigned short e2 [ MAX_MULTI ] = { 0 } ; /// 15 bit
unsigned long long e_t [ MAX_MULTI ] = { 0 } ; /// timestamp 47 bit
unsigned short e_f [ MAX_MULTI ] = { 0 } ; /// fine time 10 bit
2024-01-25 18:34:58 -05:00
bool pileUp [ MAX_MULTI ] = { false } ;
2024-01-16 15:39:41 -05:00
tree - > Branch ( " evID " , & evID , " event_ID/l " ) ;
2024-01-19 19:24:51 -05:00
tree - > Branch ( " multi " , & multi , " multi/i " ) ;
2024-01-16 15:39:41 -05:00
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_timestamp[multi]/l " ) ;
tree - > Branch ( " e_f " , e_f , " e_timestamp[multi]/s " ) ;
2024-01-25 18:34:58 -05:00
tree - > Branch ( " pileUp " , pileUp , " pileUp[multi]/O " ) ;
2024-01-12 19:12:37 -05:00
2024-01-16 15:39:41 -05:00
//TClonesArray * arrayTrace = nullptr;
//unsigned short traceLength[MAX_MULTI] = {0};
//TGraph * trace = nullptr;
2024-01-20 01:01:10 -05:00
// if( traceOn ) {
2024-01-16 15:39:41 -05:00
// arrayTrace = new TClonesArray("TGraph");
// tree->Branch("traceLength", traceLength, "traceLength[multi]/s");
// tree->Branch("trace", arrayTrace, 2560000);
// arrayTrace->BypassStreamer();
2024-01-20 01:01:10 -05:00
// }
2024-01-12 19:12:37 -05:00
//*====================================== build events
printf ( " ================= Building events.... \n " ) ;
2024-01-16 15:39:41 -05:00
std : : vector < Hit > event ;
Hit temp ;
ullong t0 = - 1 ;
uShort group0 = - 1 ;
2024-01-12 19:12:37 -05:00
2024-01-16 15:39:41 -05:00
uInt hitProcessed = 0 ;
2024-01-12 19:12:37 -05:00
2024-01-20 01:44:13 -05:00
ullong tStart = 0 ;
ullong tEnd = 0 ;
2024-01-12 19:12:37 -05:00
do {
2024-01-16 15:39:41 -05:00
event . clear ( ) ;
t0 = - 1 ;
2024-01-20 01:44:13 -05:00
/// Find earliest time
2024-01-16 15:39:41 -05:00
for ( int gpID = 0 ; gpID < nGroup ; gpID + + ) {
if ( group [ gpID ] . finished ) continue ;
//when all hit are used, go to next file or make the group.finished = true
if ( group [ gpID ] . hitID > = group [ gpID ] . hitCount ) {
2024-01-19 19:24:51 -05:00
// printf(" group ID : %d, reader ID : %d is finished. \n", gpID, group[gpID].readerIDList[group[gpID].currentID]);
2024-01-16 15:39:41 -05:00
group [ gpID ] . currentID + + ;
if ( group [ gpID ] . currentID > = group [ gpID ] . readerIDList . size ( ) ) {
group [ gpID ] . finished = true ;
printf ( " -----> no more file for this group, S/N : %d. \n " , group [ gpID ] . sn ) ;
continue ;
} else {
group [ gpID ] . hitID = 0 ;
uShort rID = group [ gpID ] . readerIDList [ group [ gpID ] . currentID ] ;
2024-06-19 16:55:38 -04:00
group [ gpID ] . hitCount = reader [ rID ] - > GetTotalHitCount ( ) ;
2024-01-22 13:56:18 -05:00
printf ( " -----> go to the next file, %s \n " , fileInfo [ rID ] . fileName . c_str ( ) ) ;
2024-01-16 15:39:41 -05:00
}
}
uShort rID = group [ gpID ] . readerIDList [ group [ gpID ] . currentID ] ;
ulong hitID = group [ gpID ] . hitID ;
ullong t = reader [ rID ] - > GetHit ( hitID ) . timestamp ;
if ( t < t0 ) {
t0 = t ;
group0 = gpID ;
}
}
2024-01-22 13:56:18 -05:00
if ( debug ) printf ( " the eariliest time is %llu at Group : %u, hitID : %lu, %s \n " , t0 , group0 , group [ group0 ] . hitID , fileInfo [ group [ group0 ] . currentID ] . fileName . c_str ( ) ) ;
2024-01-16 15:39:41 -05:00
2024-01-25 18:34:58 -05:00
if ( hitProcessed % 10000 = = 0 ) printf ( " hit Porcessed %u/%u....%.2f%% \n \033 [A \r " , hitProcessed , totHitCount , hitProcessed * 100. / totHitCount ) ;
2024-01-16 15:39:41 -05:00
2024-01-12 19:12:37 -05:00
for ( int i = 0 ; i < nGroup ; i + + ) {
2024-01-16 15:39:41 -05:00
uShort gpID = ( i + group0 ) % nGroup ;
if ( group [ gpID ] . finished ) continue ;
uShort rID = group [ gpID ] . readerIDList [ group [ gpID ] . currentID ] ;
for ( ulong iHit = group [ gpID ] . hitID ; iHit < group [ gpID ] . hitCount ; iHit + + ) {
2024-01-12 19:12:37 -05:00
2024-01-16 15:39:41 -05:00
if ( reader [ rID ] - > GetHit ( iHit ) . timestamp - t0 < = timeWindow ) {
2024-01-12 19:12:37 -05:00
2024-01-16 15:39:41 -05:00
event . push_back ( reader [ rID ] - > GetHit ( iHit ) ) ;
group [ gpID ] . hitID + + ;
hitProcessed + + ;
2024-01-12 19:12:37 -05:00
2024-01-16 15:39:41 -05:00
} else {
break ;
}
if ( timeWindow = = 0 ) break ;
}
if ( timeWindow = = 0 ) break ;
2024-01-12 19:12:37 -05:00
}
2024-01-16 15:39:41 -05:00
if ( event . size ( ) > 1 ) {
std : : sort ( event . begin ( ) , event . end ( ) , [ ] ( const Hit & a , const Hit & b ) {
return a . timestamp < b . timestamp ;
} ) ;
}
2024-01-12 19:12:37 -05:00
2024-01-16 15:39:41 -05:00
multi = event . size ( ) ;
if ( debug ) printf ( " ########### evID : %llu, multi : %u \n " , evID , multi ) ;
2024-01-20 01:44:13 -05:00
if ( evID = = 0 ) tStart = event . front ( ) . timestamp ;
2024-01-16 15:39:41 -05:00
2024-01-20 01:44:13 -05:00
if ( multi > 0 ) {
2024-01-20 13:35:19 -05:00
if ( hitProcessed > = totHitCount ) tEnd = event . back ( ) . timestamp ;
2024-01-20 01:44:13 -05:00
for ( size_t j = 0 ; j < multi ; j + + ) {
2024-01-16 15:39:41 -05:00
2024-01-25 18:34:58 -05:00
sn [ j ] = event [ j ] . sn ;
ch [ j ] = event [ j ] . ch ;
e [ j ] = event [ j ] . energy ;
e2 [ j ] = event [ j ] . energy2 ;
e_t [ j ] = event [ j ] . timestamp ;
e_f [ j ] = event [ j ] . fineTime ;
pileUp [ j ] = event [ j ] . pileUp ;
2024-01-16 15:39:41 -05:00
2024-01-20 01:44:13 -05:00
if ( debug ) event [ j ] . Print ( ) ;
}
2024-01-16 15:39:41 -05:00
2024-01-20 01:44:13 -05:00
outRootFile - > cd ( ) ;
tree - > Fill ( ) ;
evID + + ;
}
2024-01-16 15:39:41 -05:00
//check if all groups are finished
int gpCount = 0 ;
for ( size_t i = 0 ; i < group . size ( ) ; i + + ) {
if ( group [ i ] . finished ) gpCount + + ;
}
2024-01-20 01:44:13 -05:00
if ( gpCount = = ( int ) group . size ( ) ) {
break ;
}
2024-01-16 15:39:41 -05:00
} while ( true ) ;
2024-01-12 19:12:37 -05:00
2024-01-16 15:39:41 -05:00
tree - > Write ( ) ;
2024-01-12 19:12:37 -05:00
2024-01-25 18:34:58 -05:00
uInt runEndTime = getTime_us ( ) ;
2024-01-20 01:44:13 -05:00
double runTime = ( runEndTime - runStartTime ) * 1e-6 ;
2024-01-16 15:39:41 -05:00
printf ( " ========================= finished. \n " ) ;
2024-01-20 01:44:13 -05:00
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 ( ) ) ;
double tDuration_sec = ( tEnd - tStart ) * 1e-9 ;
printf ( " first timestamp = %20llu ns \n " , tStart ) ;
printf ( " last timestamp = %20llu ns \n " , tEnd ) ;
printf ( " total data duration = %.2f sec = %.2f min \n " , tDuration_sec , tDuration_sec / 60. ) ;
2024-01-16 15:39:41 -05:00
printf ( " =======> saved to %s \n " , outFileName . Data ( ) ) ;
2024-01-12 19:12:37 -05:00
2024-02-19 11:53:29 -05:00
TMacro info ;
info . AddLine ( Form ( " tStart= %20llu ns " , tStart ) ) ;
info . AddLine ( Form ( " tEnd= %20llu ns " , tEnd ) ) ;
info . Write ( " info " ) ;
2024-01-16 15:39:41 -05:00
outRootFile - > Close ( ) ;
2024-01-12 19:12:37 -05:00
for ( int i = 0 ; i < nFile ; i + + ) delete reader [ i ] ;
delete [ ] reader ;
}