2024-01-12 19:12:37 -05:00
# include "fsuReader.h"
2024-01-16 15:39:41 -05:00
# include <chrono>
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"
# define MAX_MULTI 100
# define ORDERSHIFT 100000
struct FileInfo {
TString fileName ;
unsigned int fileSize ;
unsigned int SN ;
unsigned long hitCount ;
unsigned short DPPType ;
unsigned short tick2ns ;
unsigned short order ;
unsigned short readerID ;
unsigned ID ; // sn + 100000 * order
2024-01-18 18:55:37 -05:00
void CalOrder ( ) { ID = ORDERSHIFT * SN + order ; }
2024-01-12 19:12:37 -05:00
void Print ( ) {
printf ( " %6d | %3d | %30s | %2d | %6lu | %u Bytes = %.2f MB \n " ,
2024-01-16 15:39:41 -05:00
ID , DPPType , fileName . Data ( ) , tick2ns , hitCount , fileSize , fileSize / 1024. / 1024. ) ;
2024-01-12 19:12:37 -05:00
}
} ;
struct GroupInfo {
std : : vector < unsigned short > readerIDList ;
2024-01-16 15:39:41 -05:00
uInt sn ;
unsigned short currentID ; // the ID of the readerIDList;
ulong hitCount ; // this is the hitCount for the currentID;
ulong hitID ; // this is the ID for the reader->GetHit(hitID);
bool finished ;
2024-01-12 19:12:37 -05:00
} ;
2024-01-16 15:39:41 -05:00
unsigned long long getTime_ns ( ) {
std : : chrono : : high_resolution_clock : : time_point currentTime = std : : chrono : : high_resolution_clock : : now ( ) ;
std : : chrono : : nanoseconds nanoseconds = std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( currentTime . time_since_epoch ( ) ) ;
return nanoseconds . count ( ) ;
}
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 " ) ;
printf ( " Output file name is contructed from inFile1 \n " ) ;
return 1 ;
}
2024-01-18 18:55:37 -05:00
/// File format must be YYY...Y_runXXX_AAA_BBB_TT_CCC.fsu
2024-01-12 19:12:37 -05:00
/// YYY...Y = prefix
/// XXX = runID, 3 digits
/// AAA = board Serial Number, 3 digits
/// BBB = DPPtype, 3 digits
2024-01-18 18:55:37 -05:00
/// TT = tick2ns, any digits
2024-01-12 19:12:37 -05:00
/// CCC = over size index, 3 digits
///============= read input
unsigned int timeWindow = atoi ( argv [ 1 ] ) ;
//float bufferSize = atof(argv[2]);
//bool traceOn = atoi(argv[3]);
bool traceOn = false ;
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 ] ;
int pos = outFileName . Index ( " _ " ) ;
pos = outFileName . Index ( " _ " , pos + 1 ) ;
outFileName . Remove ( pos ) ;
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 ) ;
reader [ i ] = new FSUReader ( inFileName [ i ] . Data ( ) , false ) ;
2024-01-18 18:55:37 -05:00
reader [ i ] - > ScanNumBlock ( 0 , 1 ) ;
2024-01-16 15:39:41 -05:00
// reader[i]->FillHitList();
2024-01-12 19:12:37 -05:00
FileInfo tempInfo ;
tempInfo . fileName = inFileName [ i ] ;
tempInfo . readerID = i ;
tempInfo . SN = reader [ i ] - > GetSN ( ) ;
tempInfo . hitCount = reader [ i ] - > GetHitCount ( ) ;
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 ( ) ) ;
uLong hitCount = reader [ rID ] - > GetHitCount ( ) ;
2024-01-18 18:55:37 -05:00
for ( uLong k = 0 ; k < ( hitCount < 5 ? hitCount : 10 ) ; k + + ) { reader [ rID ] - > GetHit ( k ) . Print ( ) ; }
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 ) ;
unsigned long long evID = - 1 ;
unsigned short multi = 0 ;
unsigned short sn [ MAX_MULTI ] = { 0 } ; /// board SN
//unsigned short bd[MAX_MULTI] = {0}; /// boardID
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
tree - > Branch ( " evID " , & evID , " event_ID/l " ) ;
tree - > Branch ( " multi " , & multi , " multi/s " ) ;
tree - > Branch ( " sn " , sn , " sn[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 ( " 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-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;
if ( traceOn ) {
// arrayTrace = new TClonesArray("TGraph");
// tree->Branch("traceLength", traceLength, "traceLength[multi]/s");
// tree->Branch("trace", arrayTrace, 2560000);
// arrayTrace->BypassStreamer();
}
2024-01-12 19:12:37 -05:00
//*====================================== build events
printf ( " ================= Building events.... \n " ) ;
2024-01-16 15:39:41 -05:00
evID = 0 ;
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
do {
2024-01-16 15:39:41 -05:00
event . clear ( ) ;
t0 = - 1 ;
//// Find earliest time
// ullong torg = getTime_ns();
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 ) {
printf ( " group ID : %d, reader ID : %d is finished. \n " , gpID , group [ gpID ] . readerIDList [ group [ gpID ] . currentID ] ) ;
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 ] ;
group [ gpID ] . hitCount = reader [ rID ] - > GetHitCount ( ) ;
printf ( " -----> go to the next file, %s \n " , fileInfo [ rID ] . fileName . Data ( ) ) ;
}
}
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 ;
}
}
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 . Data ( ) ) ;
// ullong t1 = getTime_ns();
// printf("Find earliest Time used : %llu ns \n", t1 - torg);
2024-01-12 19:12:37 -05:00
2024-01-16 15:39:41 -05:00
printf ( " hit Porcessed %u/%u....%.2f%% \n \033 [A \r " , hitProcessed , totHitCount , hitProcessed * 100. / totHitCount ) ;
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
// ullong t2 = getTime_ns();
// printf(" getting an event used %llu ns\n", t2 - t1);
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 ) ;
if ( multi = = 0 ) break ;
// ullong t3 = getTime_ns();
// printf(" sort event used %llu ns\n", t3 - t2);
for ( size_t j = 0 ; j < multi ; j + + ) {
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 ;
if ( debug ) event [ j ] . Print ( ) ;
}
outRootFile - > cd ( ) ;
tree - > Fill ( ) ;
// ullong t4 = getTime_ns();
// printf(" Fill tree used %llu ns\n", t4 - t3);
//check if all groups are finished
int gpCount = 0 ;
for ( size_t i = 0 ; i < group . size ( ) ; i + + ) {
if ( group [ i ] . finished ) gpCount + + ;
}
if ( gpCount = = ( int ) group . size ( ) ) break ;
evID + + ;
} 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-16 15:39:41 -05:00
printf ( " ========================= finished. \n " ) ;
printf ( " total events built = %llu(%llu) \n " , evID , tree - > GetEntriesFast ( ) ) ;
printf ( " =======> saved to %s \n " , outFileName . Data ( ) ) ;
2024-01-12 19:12:37 -05:00
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 ;
}