From 282aa5eceaae41c6cfb549d0b809d2725c62b817 Mon Sep 17 00:00:00 2001 From: vsitaraman Date: Tue, 10 Feb 2026 17:01:27 -0500 Subject: [PATCH] modified: .gitignore new file: Armory/ClassData.h new file: Armory/Hit.h modified: Armory/Makefile new file: Armory/fsuReader.h new file: Armory/macro.h new file: BatchProcess.sh modified: ProcessRun.sh modified: process_mapped_run.sh --- .gitignore | 2 + Armory/ClassData.h | 1270 +++++++++++++++++++++++++++++++++++++++++ Armory/Hit.h | 52 ++ Armory/Makefile | 2 +- Armory/fsuReader.h | 795 ++++++++++++++++++++++++++ Armory/macro.h | 56 ++ BatchProcess.sh | 6 + ProcessRun.sh | 12 +- process_mapped_run.sh | 4 +- 9 files changed, 2190 insertions(+), 9 deletions(-) create mode 100644 Armory/ClassData.h create mode 100644 Armory/Hit.h create mode 100644 Armory/fsuReader.h create mode 100644 Armory/macro.h create mode 100644 BatchProcess.sh diff --git a/.gitignore b/.gitignore index a653e4c..a78f54b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ EventBuilder* *.root *.exe *.txt +*.err +*.seq Mapper AnasenMS diff --git a/Armory/ClassData.h b/Armory/ClassData.h new file mode 100644 index 0000000..92cbed4 --- /dev/null +++ b/Armory/ClassData.h @@ -0,0 +1,1270 @@ +#ifndef DATA_H +#define DATA_H + +#include +#include +#include +#include +#include ///memset +#include ///cout +#include +#include // for setw +#include +#include +#include +#include + +#include "macro.h" + +//#define MaxNData 10000 /// store 10k events per channels +#define DefaultDataSize 10000 + +enum DPPTypeCode{ + DPP_PHA_CODE = 0x8B, + DPP_PSD_CODE = 0x88, + DPP_QDC_CODE = 0x87 +}; + +enum ModelTypeCode{ + VME = 0, + DT = 1 +}; + +class Data{ + + public: + char * buffer; /// readout buffer + int DPPType; + std::string DPPTypeStr; /// only for saving fiel name + unsigned short boardSN; + int tick2ns; /// use in convert the timestamp to ns, and use in TriggerRate calculation + + unsigned int nByte; /// number of byte from read buffer + uint32_t AllocatedSize; + + float TriggerRate [MaxNChannels]; /// Hz + float NonPileUpRate [MaxNChannels]; /// Hz + unsigned long TotNumNonPileUpEvents[MaxNChannels]; /// also exclude overthrow + unsigned short NumEventsDecoded [MaxNChannels]; /// reset after trig-rate calculation + unsigned short NumNonPileUpDecoded [MaxNChannels]; /// reset after trig-rate calculation + uShort countNumEventDecodeZero[MaxNChannels]; /// when > 3, set trigger rate to be zero; + + unsigned int TotalAggCount ; + unsigned short AggCount ; /// reset after trig-rate calculation + unsigned int aggTime; /// update every decode + + int GetLoopIndex(unsigned short ch) const {return LoopIndex[ch];} + int GetDataIndex(unsigned short ch) const {return DataIndex[ch];} + + uShort GetDataSize() const {return dataSize;} + + ullong GetTimestamp(unsigned short ch, unsigned int index) const {return Timestamp[ch][index];} + uShort GetFineTime(unsigned short ch, unsigned int index) const {return fineTime[ch][index];} + uShort GetEnergy(unsigned short ch, unsigned int index) const {return Energy[ch][index];} + uShort GetEnergy2(unsigned short ch, unsigned int index) const {return Energy2[ch][index];} + bool GetPileUp(unsigned short ch, unsigned int index) const {return PileUp[ch][index];} + + uInt GetWordIndex() const {return nw;} + + std::vector ** Waveform1 ; // used at least 14 MB + std::vector ** Waveform2 ; + std::vector ** DigiWaveform1; + std::vector ** DigiWaveform2; + std::vector ** DigiWaveform3; + std::vector ** DigiWaveform4; + + + public: + Data(unsigned short numCh, uInt dataSize = DefaultDataSize); + ~Data(); + + void Allocate80MBMemory(); + void AllocateMemory(uint32_t size); + + void AllocateDataSize(int dataSize); + void ClearDataPointer(); + void ClearData(); + void ClearTriggerRate(); + void ClearNumEventsDecoded(); + void ClearBuffer(); + + unsigned short GetNChannel() const {return numInputCh;} + + void CopyBuffer( const char * buffer, const unsigned int size); + + void DecodeBuffer(bool fastDecode, int verbose = 0); /// fastDecode will not save waveform + void DecodeBuffer(char * &buffer, unsigned int size, bool fastDecode, int verbose = 0); // for outside data + + void DecodeDualBlock(char * &buffer, unsigned int size, int DPPType, int chMask, bool fastDecode, int verbose = 0); // for outside data + + void PrintStat(bool skipEmpty = true); + void PrintAllData(bool tableMode = true, unsigned int maxRowDisplay = 0) const; + void PrintChData(unsigned short ch, unsigned int maxRowDisplay = 0) const; + + //^================= Saving data + bool OpenSaveFile(std::string fileNamePrefix); // return false when fail + std::string GetOutFileName() const {return outFileName;} + void SaveData(); + void CloseSaveFile(); + unsigned int GetFileSize() const {return outFileSize;} + uint64_t GetTotalFileSize() const {return FinishedOutFilesSize + outFileSize;} + void ZeroTotalFileSize() { FinishedOutFilesSize = 0; } + + void CalTriggerRate(); // this method is called by FSUDAQ::UpdateScalar() + void ClearReferenceTime(); + + protected: + + const unsigned short numInputCh; + unsigned int nw; + + int dataSize; + + int LoopIndex[MaxNChannels]; /// number of loop in the circular memory + int DataIndex[MaxNChannels]; + + ullong ** Timestamp; /// 47 bit + uShort ** fineTime; /// 10 bits, in unit of tick2ns / 1000 = ps + uShort ** Energy ; /// 15 bit + uShort ** Energy2 ; /// 15 bit, in PSD, Energy = Qshort, Energy2 = Qlong + bool ** PileUp ; /// pile up flag + + ///for temperary + std::vector tempWaveform1; + std::vector tempWaveform2; + std::vector tempDigiWaveform1; + std::vector tempDigiWaveform2; + std::vector tempDigiWaveform3; + std::vector tempDigiWaveform4; + + FILE * outFile; + uint64_t FinishedOutFilesSize; // sum of files size. + unsigned int outFileIndex; + std::string outFilePrefix; + std::string outFileName; + unsigned int outFileSize; // should be max at 2 GB + + ullong t0[MaxNChannels]; // for trigger rate calculation + + short calIndexes[MaxNChannels][2]; /// the index for trigger rate calculation + + unsigned int ReadBuffer(unsigned int nWord, int verbose = 0); + + int DecodePHADualChannelBlock(unsigned int ChannelMask, bool fastDecode, int verbose); + int DecodePSDDualChannelBlock(unsigned int ChannelMask, bool fastDecode, int verbose); + int DecodeQDCGroupedChannelBlock(unsigned int ChannelMask, bool fastDecode, int verbose); +}; + +//========================================== + +inline Data::Data(unsigned short numCh, uInt dataSize): numInputCh(numCh){ + tick2ns = 2.0; + boardSN = 0; + DPPType = DPPTypeCode::DPP_PHA_CODE; + DPPTypeStr = ""; + buffer = NULL; + + AllocateDataSize(dataSize); + + for ( int i = 0; i < MaxNChannels; i++) { + TotNumNonPileUpEvents[i] = 0; + t0[i] = 0; + countNumEventDecodeZero[i] = 0; + } + ClearData(); + ClearTriggerRate(); + ClearNumEventsDecoded(); + nw = 0; + + outFileIndex = 0; + outFilePrefix = ""; + outFileName = ""; + outFile = nullptr; + outFileSize = 0; // should be max at 2 GB + FinishedOutFilesSize = 0; // sum of files size. + +} + +inline Data::~Data(){ + if( buffer != NULL ) delete buffer; + + ClearDataPointer(); +} + +inline void Data::AllocateDataSize(int dataSize){ + + if( dataSize < 1) { + printf("dataSize cannot < 1, set dataSize = 1.\n"); + dataSize = 1; + } + //printf("Data::%s, size: %u, No. Ch: %u\n", __func__, dataSize, numInputCh); + + this->dataSize = dataSize; + + Timestamp = new ullong * [numInputCh]; + fineTime = new uShort * [numInputCh]; + Energy = new uShort * [numInputCh]; + Energy2 = new uShort * [numInputCh]; + PileUp = new bool * [numInputCh]; + + Waveform1 = new std::vector * [numInputCh]; + Waveform2 = new std::vector * [numInputCh]; + DigiWaveform1 = new std::vector * [numInputCh]; + DigiWaveform2 = new std::vector * [numInputCh]; + DigiWaveform3 = new std::vector * [numInputCh]; + DigiWaveform4 = new std::vector * [numInputCh]; + + for(int ch = 0; ch < numInputCh; ch++){ + Timestamp[ch] = new ullong[dataSize]; + fineTime[ch] = new uShort[dataSize]; + Energy[ch] = new uShort[dataSize]; + Energy2[ch] = new uShort[dataSize]; + PileUp[ch] = new bool[dataSize]; + + Waveform1[ch] = new std::vector [dataSize]; + Waveform2[ch] = new std::vector [dataSize]; + DigiWaveform1[ch] = new std::vector [dataSize]; + DigiWaveform2[ch] = new std::vector [dataSize]; + DigiWaveform3[ch] = new std::vector [dataSize]; + DigiWaveform4[ch] = new std::vector [dataSize]; + } + +} + +inline void Data::ClearDataPointer(){ + + if( dataSize == 0) return; + + for(int ch = 0; ch < numInputCh; ch++){ + delete [] Timestamp[ch] ; + delete [] fineTime[ch]; + delete [] Energy[ch]; + delete [] Energy2[ch]; + delete [] PileUp[ch]; + + delete [] Waveform1[ch]; + delete [] Waveform2[ch]; + delete [] DigiWaveform1[ch]; + delete [] DigiWaveform2[ch]; + delete [] DigiWaveform3[ch]; + delete [] DigiWaveform4[ch]; + } + + delete [] Timestamp; + delete [] fineTime; + delete [] Energy; + delete [] Energy2; + delete [] PileUp; + + delete [] Waveform1; + delete [] Waveform2; + delete [] DigiWaveform1; + delete [] DigiWaveform2; + delete [] DigiWaveform3; + delete [] DigiWaveform4; + + dataSize = 0; + +} + +inline void Data::AllocateMemory(uint32_t size){ + ClearBuffer(); + AllocatedSize = size; + buffer = (char *) malloc( AllocatedSize); + printf("Allocated %u byte ( %.2f MB) for buffer = %u words\n", AllocatedSize, AllocatedSize/1024./1024., AllocatedSize / 4); +} + +inline void Data::Allocate80MBMemory(){ + AllocateMemory( 80 * 1024 * 1024 ); /// 80 M Byte +} + +inline void Data::ClearTriggerRate(){ + for( int i = 0 ; i < MaxNChannels; i++) { + TriggerRate[i] = 0.0; + NonPileUpRate[i] = 0.0; + } +} + +inline void Data::ClearNumEventsDecoded(){ + for( int i = 0 ; i < MaxNChannels; i++) { + NumEventsDecoded[i] = 0; + NumNonPileUpDecoded[i] = 0; + countNumEventDecodeZero[i] = 0; + } + AggCount = 0; +} + +inline void Data::ClearData(){ + nByte = 0; + AllocatedSize = 0; + TotalAggCount = 0; + for( int ch = 0 ; ch < MaxNChannels; ch++){ + LoopIndex[ch] = 0; + DataIndex[ch] = -1; + + TotNumNonPileUpEvents[ch] = 0 ; + + calIndexes[ch][0] = -1; + calIndexes[ch][1] = -1; + + if( ch >= numInputCh) break; + for( int j = 0; j < dataSize; j++){ + Timestamp[ch][j] = 0; + fineTime[ch][j] = 0; + Energy[ch][j] = 0; + Energy2[ch][j] = 0; + Waveform1[ch][j].clear(); + Waveform2[ch][j].clear(); + DigiWaveform1[ch][j].clear(); + DigiWaveform2[ch][j].clear(); + DigiWaveform3[ch][j].clear(); + DigiWaveform4[ch][j].clear(); + } + + } + + tempWaveform1.clear(); + tempWaveform2.clear(); + tempDigiWaveform1.clear(); + tempDigiWaveform2.clear(); + tempDigiWaveform3.clear(); + tempDigiWaveform4.clear(); + + ClearNumEventsDecoded(); + ClearTriggerRate(); + +} + +inline void Data::ClearBuffer(){ + //printf("==== Data::%s \n", __func__); + delete buffer; + buffer = nullptr; + AllocatedSize = 0; + nByte = 0; +} + +inline void Data::CopyBuffer(const char * buffer, const unsigned int size){ + std::memcpy(this->buffer, buffer, size); +} + +inline void Data::ClearReferenceTime(){ + for( int ch = 0; ch < numInputCh; ch ++ ) t0[ch] = 0; +} + +inline void Data::CalTriggerRate(){ // this method is called by FSUDAQ::UpdateScalar() + + unsigned long long dTime = 0; + double sec = -999; + + for( int ch = 0; ch < numInputCh; ch ++ ){ + if( t0[ch] == 0 || countNumEventDecodeZero[ch] > 3) { + TriggerRate[ch] = 0; + NonPileUpRate[ch] = 0; + countNumEventDecodeZero[ch] = 0; + continue; + } + + if( NumEventsDecoded[ch] == 0 ) { + countNumEventDecodeZero[ch] ++; + continue; + } + + if( NumEventsDecoded[ch] < dataSize ){ + + dTime = Timestamp[ch][DataIndex[ch]] - t0[ch]; + double sec = dTime / 1e9; + + TriggerRate[ch] = (NumEventsDecoded[ch])/sec; + NonPileUpRate[ch] = (NumNonPileUpDecoded[ch])/sec; + + // printf("%2d | %d | %f %f \n", ch, NumEventsDecoded[ch], sec, TriggerRate[ch]); + + }else{ + + uShort nEvent = 100; + dTime = Timestamp[ch][DataIndex[ch]] - Timestamp[ch][DataIndex[ch] - 100]; + sec = dTime / 1e9; + + TriggerRate[ch] = (nEvent)/sec; + NonPileUpRate[ch] = (NumNonPileUpDecoded[ch])/sec * (nEvent)/(NumEventsDecoded[ch]); + + } + + if( std::isinf(TriggerRate[ch]) ) { + printf("%2d | %d(%d)| %llu %llu | %d %d | %llu, %.3e | %.2f, %.2f\n", ch, DataIndex[ch], LoopIndex[ch], + t0[ch], Timestamp[ch][DataIndex[ch]], + NumEventsDecoded[ch], NumNonPileUpDecoded[ch], + dTime, sec , + TriggerRate[ch], NonPileUpRate[ch]); + } + + t0[ch] = Timestamp[ch][DataIndex[ch]]; + NumEventsDecoded[ch] = 0; + NumNonPileUpDecoded[ch] = 0; + } + + AggCount = 0; +} + +//^############################################### +//^############################################### Save fsu file +inline bool Data::OpenSaveFile(std::string fileNamePrefix){ + + outFilePrefix = fileNamePrefix; + + std::ostringstream oss; + oss << outFilePrefix << "_" + << std::setfill('0') << std::setw(3) << boardSN << "_" + << DPPTypeStr << "_" + << std::fixed << std::setprecision(0) << tick2ns << "_" + << std::setfill('0') << std::setw(3) << outFileIndex << ".fsu"; + std::string saveFileName = oss.str(); + + //char saveFileName[100]; + //sprintf(saveFileName, "%s_%03d_%3s_%03u.fsu", outFilePrefix.c_str() , boardSN, DPPTypeStr.c_str(), outFileIndex); + + outFileName = saveFileName; + outFile = fopen(saveFileName.c_str(), "wb"); // overwrite binary + + if (outFile == NULL) { + printf("Failed to open the file. Probably Read-ONLY.\n"); + return false; + } + + fseek(outFile, 0L, SEEK_END); + outFileSize = ftell(outFile); + + return true; +} + +inline void Data::SaveData(){ + + if( buffer == nullptr) { + printf("buffer is null.\n"); + return; + } + + if( outFile == nullptr ) return; + + if( outFileSize > (unsigned int) MaxSaveFileSize){ + FinishedOutFilesSize += ftell(outFile); + CloseSaveFile(); + outFileIndex ++; + + // char saveFileName[100]; + // sprintf(saveFileName, "%s_%03d_%3s_%03u.fsu", outFilePrefix.c_str() , boardSN, DPPTypeStr.c_str(), outFileIndex); + + std::ostringstream oss; + oss << outFilePrefix << "_" + << std::setfill('0') << std::setw(3) << boardSN << "_" + << DPPTypeStr << "_" + << std::fixed << std::setprecision(0) << tick2ns << "_" + << std::setfill('0') << std::setw(3) << outFileIndex << ".fsu"; + std::string saveFileName = oss.str(); + + outFileName = saveFileName; + outFile = fopen(outFileName.c_str(), "wb"); //overwrite binary + } + + fwrite(buffer, nByte, 1, outFile); + outFileSize = ftell(outFile); + +} +inline void Data::CloseSaveFile(){ + if( outFile != nullptr ){ + fclose(outFile); + outFile = nullptr; + int result = chmod(outFileName.c_str(), S_IRUSR | S_IRGRP | S_IROTH); + if( result != 0 ) printf("somewrong when set file (%s) to read only.", outFileName.c_str()); + } +} + +//^####################################################### +//^####################################################### Print +inline void Data::PrintStat(bool skipEmpty) { + + printf("============================= Print Stat. Digi-%d, TotalAggCount = %d\n", boardSN, TotalAggCount); + printf("%2s | %6s | %9s | %9s | %6s | %6s(%4s)\n", "ch", "# Evt.", "Rate [Hz]", "Accept", "Tot. Evt.", "index", "loop"); + printf("---+--------+-----------+-----------+----------\n"); + for(int ch = 0; ch < numInputCh; ch++){ + //if( skipEmpty && TriggerRate[ch] == 0 ) continue; + if( skipEmpty && DataIndex[ch] < 0 ) continue; + printf("%2d | %6d | %9.2f | %9.2f | %6lu | %6d(%2d)\n", ch, NumEventsDecoded[ch], TriggerRate[ch], NonPileUpRate[ch], TotNumNonPileUpEvents[ch], DataIndex[ch], LoopIndex[ch]); + } + printf("---+--------+-----------+-----------+----------\n"); + + ClearTriggerRate(); + ClearNumEventsDecoded(); + +} + +inline void Data::PrintAllData(bool tableMode, unsigned int maxRowDisplay) const{ + printf("============================= Print Data Digi-%d\n", boardSN); + + if( tableMode ){ + int entry = 0; + + int MaxEntry = 0; + printf("%4s|", ""); + for( int ch = 0; ch < numInputCh; ch++){ + if( LoopIndex[ch] > 0 ) { + MaxEntry = dataSize-1; + }else{ + if( DataIndex[ch] > MaxEntry ) MaxEntry = DataIndex[ch]; + } + if( DataIndex[ch] < 0 ) continue; + printf(" %5s-%02d,%2d,%-6d |", "ch", ch, LoopIndex[ch], DataIndex[ch]); + } + printf("\n"); + + + do{ + printf("%4d|", entry ); + for( int ch = 0; ch < numInputCh; ch++){ + if( DataIndex[ch] < 0 ) continue; + printf(" %5d,%17lld |", Energy[ch][entry], Timestamp[ch][entry]); + } + printf("\n"); + entry ++; + + if( maxRowDisplay > 0 && (unsigned int) entry >= maxRowDisplay ) break; + }while(entry <= MaxEntry); + + }else{ + for( int ch = 0; ch < numInputCh ; ch++){ + if( DataIndex[ch] < 0 ) continue; + printf("------------ ch : %d, DataIndex : %d, loop : %d\n", ch, DataIndex[ch], LoopIndex[ch]); + for( int ev = 0; ev <= (LoopIndex[ch] > 0 ? dataSize : DataIndex[ch]) ; ev++){ + if( DPPType == DPPTypeCode::DPP_PHA_CODE || DPPType == DPPTypeCode::DPP_QDC_CODE ) printf("%4d, %5u, %18llu, %5u \n", ev, Energy[ch][ev], Timestamp[ch][ev], fineTime[ch][ev]); + if( DPPType == DPPTypeCode::DPP_PSD_CODE ) printf("%4d, %5u, %5u, %18llu, %5u \n", ev, Energy[ch][ev], Energy2[ch][ev], Timestamp[ch][ev], fineTime[ch][ev]); + if( maxRowDisplay > 0 && (unsigned int) ev > maxRowDisplay ) break; + } + } + } +} + +inline void Data::PrintChData(unsigned short ch, unsigned int maxRowDisplay) const{ + + if( DataIndex[ch] < 0 ) printf("no data in ch-%d\n", ch); + printf("------------ ch : %d, DataIndex : %d, loop : %d\n", ch, DataIndex[ch], LoopIndex[ch]); + for( int ev = 0; ev < (LoopIndex[ch] > 0 ? dataSize : DataIndex[ch]) ; ev++){ + if( DPPType == DPPTypeCode::DPP_PHA_CODE || DPPType == DPPTypeCode::DPP_QDC_CODE ) printf("%4d, %5u, %15llu, %5u \n", ev, Energy[ch][ev], Timestamp[ch][ev], fineTime[ch][ev]); + if( DPPType == DPPTypeCode::DPP_PSD_CODE ) printf("%4d, %5u, %5u, %15llu, %5u \n", ev, Energy[ch][ev], Energy2[ch][ev], Timestamp[ch][ev], fineTime[ch][ev]); + if( maxRowDisplay > 0 && (unsigned int) ev > maxRowDisplay ) break; + } + +} + +//^####################################################### +//^####################################################### Decode +inline unsigned int Data::ReadBuffer(unsigned int nWord, int verbose){ + if( buffer == NULL ) return 0; + + unsigned int word = 0; + for( int i = 0 ; i < 4 ; i++) word += ((buffer[i + 4 * nWord] & 0xFF) << 8*i); + if( verbose >= 2) printf("%6d | 0x%08X | ", nWord, word); + return word; +} + +inline void Data::DecodeBuffer(char * &buffer, unsigned int size, bool fastDecode, int verbose){ + this->buffer = buffer; + this->nByte = size; + DecodeBuffer(fastDecode, verbose); +} + +inline void Data::DecodeBuffer(bool fastDecode, int verbose){ + /// verbose : 0 = off, 1 = only energy + timestamp, 2 = show header, 3 = wave + + if( buffer == NULL ) { + if( verbose >= 1 ) printf(" buffer is empty \n"); + return; + } + + //for( int ch = 0; ch < MaxNChannels; ch ++) { + // NumEventsDecoded[ch] = 0; + // NumNonPileUpDecoded[ch] = 0; + //} + + // if( DPPType == DPPType::DPP_QDC_CODE ) verbose = 10; + + if( nByte == 0 ) return; + nw = 0; + + //printf("############################# agg\n"); + + do{ + if( verbose >= 1 ) printf("Data::DecodeBuffer ######################################### Board Agg.\n"); + unsigned int word = ReadBuffer(nw, verbose); + if( ( (word >> 28) & 0xF ) == 0xA ) { /// start of Board Agg + unsigned int nWord = word & 0x0FFFFFFF ; + if( verbose >= 1 ) printf("Number of words in this Agg : %u = %u Byte\n", nWord, nWord * 4); + AggCount ++; + TotalAggCount ++; + + nw = nw + 1; word = ReadBuffer(nw, verbose); + unsigned int BoardID = ((word >> 27) & 0x1F); + unsigned short pattern = ((word >> 8 ) & 0x7FFF ); + bool BoardFailFlag = ((word >> 26) & 0x1 ); + unsigned int ChannelMask = ( word & 0xFF ) ; + if( verbose >= 1 ) printf("Board ID(type) : %d, FailFlag = %d, Patten = %u, ChannelMask = 0x%X\n", + BoardID, BoardFailFlag, pattern, ChannelMask); + + if( BoardID > 0 ) { + switch(BoardID){ + case 0x8 : DPPType = DPPTypeCode::DPP_PSD_CODE; break; + case 0xB : DPPType = DPPTypeCode::DPP_PHA_CODE; break; + case 0x7 : DPPType = DPPTypeCode::DPP_QDC_CODE; break; + } + } + + nw = nw + 1; + unsigned int bdAggCounter = ReadBuffer(nw, verbose); + if( verbose >= 1 ) printf("Board Agg Counter : %u \n", bdAggCounter & 0x7FFFFF); + + nw = nw + 1; + aggTime = ReadBuffer(nw, verbose); + if( verbose >= 1 ) printf("Agg Time Tag : %u \n", aggTime); + + for( int chMask = 0; chMask < 8 ; chMask ++ ){ // the max numnber of Coupled/RegChannel is 8 for PHA, PSD, QDC + if( ((ChannelMask >> chMask) & 0x1 ) == 0 ) continue; + if( verbose >= 2 ) printf("==================== Dual/Group Channel Block, ch Mask : 0x%X, nw : %d\n", chMask *2, nw); + + nw = nw + 1; + + if( DPPType == DPPTypeCode::DPP_PHA_CODE ) { + if ( DecodePHADualChannelBlock(chMask, fastDecode, verbose) < 0 ) break; + } + if( DPPType == DPPTypeCode::DPP_PSD_CODE ) { + if ( DecodePSDDualChannelBlock(chMask, fastDecode, verbose) < 0 ) break; + } + if( DPPType == DPPTypeCode::DPP_QDC_CODE ) { + if ( DecodeQDCGroupedChannelBlock(chMask, fastDecode, verbose) < 0 ) break; + } + } + }else{ + if( verbose >= 1 ) printf("nw : %d, incorrect buffer header. \n", nw); + break; + } + nw++; + ///printf("nw : %d ,x 4 = %d, nByte : %d \n", nw, 4*nw, nByte); + }while(4*nw < nByte); + + //Set the t0 for when frist hit comes + for( int ch = 0; ch < numInputCh; ch++){ + if( t0[ch] == 0 && DataIndex[ch] > 0 ) t0[ch] = Timestamp[ch][0]; + } + +} + +//*================================================= +inline void Data::DecodeDualBlock(char * &buffer, unsigned int size, int DPPType, int chMask, bool fastDecode, int verbose){ + this->buffer = buffer; + this->nByte = size; + + nw = 0; + + if( DPPType == DPPTypeCode::DPP_PHA_CODE ) { + DecodePHADualChannelBlock(chMask, fastDecode, verbose) ; + } + if( DPPType == DPPTypeCode::DPP_PSD_CODE ) { + DecodePSDDualChannelBlock(chMask, fastDecode, verbose) ; + } + if( DPPType == DPPTypeCode::DPP_QDC_CODE ) { + DecodeQDCGroupedChannelBlock(chMask, fastDecode, verbose) ; + } + +} + +inline int Data::DecodePHADualChannelBlock(unsigned int ChannelMask, bool fastDecode, int verbose){ + + //printf("======= %s\n", __func__); + + //nw = nw + 1; + unsigned int word = ReadBuffer(nw, verbose); + + bool hasFormatInfo = ((word >> 31) & 0x1); + unsigned int aggSize = ( word & 0x7FFFFFFF ) ; + if( verbose >= 2 ) printf("Dual Channel size : %d \n", aggSize); + unsigned int nSample = 0; /// wave form; + unsigned int nEvents = 0; + unsigned int extra2Option = 0; + bool hasWaveForm = false; + bool hasExtra2 = false; + bool hasDualTrace = 0 ; + if( hasFormatInfo ){ + nw = nw + 1; word = ReadBuffer(nw, verbose); + + nSample = ( word & 0xFFFF ) * 8; + extra2Option = ( (word >> 24 ) & 0x7 ); + hasExtra2 = ( (word >> 28 ) & 0x1 ); + if( !fastDecode || verbose >= 2){ + unsigned int digitalProbe = ( (word >> 16 ) & 0xF ); + unsigned int analogProbe2 = ( (word >> 20 ) & 0x3 ); + unsigned int analogProbe1 = ( (word >> 22 ) & 0x3 ); + hasWaveForm = ( (word >> 27 ) & 0x1 ); + bool hasTimeStamp = ( (word >> 29 ) & 0x1 ); + bool hasEnergy = ( (word >> 30 ) & 0x1 ); + hasDualTrace = ( (word >> 31 ) & 0x1 ); + + if( verbose >= 2 ) { + printf("DualTrace : %d, Energy : %d, Time: %d, Wave : %d, Extra2: %d \n", + hasDualTrace, hasEnergy, hasTimeStamp, hasWaveForm, hasExtra2); + } + if( verbose >= 3){ + if( hasExtra2 ){ + printf("...... extra 2 : "); + switch (extra2Option){ + case 0: printf("[0:15] trapwzoid baseline * 4 [16:31] Extended timestamp (16-bit)\n"); break; + case 1: printf("Reserved\n"); break; + case 2: printf("[0:9] Fine time stamp [10:15] Reserved [16:31] Extended timestamp (16-bit)\n"); break; + case 3: printf("Reserved\n"); break; + case 4: printf("[0:15] Total trigger counter [16:31] Lost trigger counter\n"); break; + case 5: printf("[0:15] Event after Zero crossing [16:31] Event before Zero crossing\n"); break; + case 6: printf("Reserved\n"); break; + case 7: printf("Reserved\n"); break; + } + } + if( hasWaveForm ){ + printf("...... Analog Probe 1 : "); + switch (analogProbe1 ){ + case 0 : printf("Input \n"); break; + case 1 : printf("RC-CR (1st derivative) \n"); break; + case 2 : printf("RC-CR2 (2st derivative) \n"); break; + case 3 : printf("trapazoid \n"); break; + } + printf("...... Analog Probe 2 : "); + switch (analogProbe2 ){ + case 0 : printf("Input \n"); break; + case 1 : printf("Theshold \n"); break; + case 2 : printf("trapezoid - baseline \n"); break; + case 3 : printf("baseline \n"); break; + } + printf("...... Digital Probe : "); + switch (digitalProbe ){ + case 0 : printf("Peaking \n"); break; + case 1 : printf("Armed (trigger) \n"); break; + case 2 : printf("Peak Run \n"); break; + case 3 : printf("Pile up \n"); break; + case 4 : printf("Peaking \n"); break; + case 5 : printf("Trigger Validation Window \n"); break; + case 6 : printf("Baseline for energy calculation \n"); break; + case 7 : printf("Trigger holdoff \n"); break; + case 8 : printf("Trigger Validation \n"); break; + case 9 : printf("ACQ Busy \n"); break; + case 10 : printf("Trigger window \n"); break; + case 11 : printf("Ext. Trigger \n"); break; + case 12 : printf("Busy = memory is full \n"); break; + } + } + } + } + nEvents = (aggSize - 2) / (nSample/2 + 2 + hasExtra2 ); + if( verbose >= 2 ) printf("----------------- nEvents : %d, fast decode : %d\n", nEvents, fastDecode); + }else{ + if( verbose >= 2 ) printf("does not has format info. unable to read buffer.\n"); + return 0; + } + + ///========== decode an event + for( unsigned int ev = 0; ev < nEvents ; ev++){ + if( verbose >= 2 ) printf("------ event : %d\n", ev); + nw = nw +1 ; word = ReadBuffer(nw, verbose); + bool channelTag = ((word >> 31) & 0x1); + unsigned int timeStamp0 = (word & 0x7FFFFFFF); + int channel = ChannelMask*2 + channelTag; + if( verbose >= 2 ) printf("ch : %d, timeStamp0 %u \n", channel, timeStamp0); + + ///===== read waveform + if( !fastDecode ) { + tempWaveform1.clear(); + tempWaveform2.clear(); + tempDigiWaveform1.clear(); + } + + unsigned int triggerAtSample = 0 ; + if( fastDecode ){ + nw += nSample/2; + }else{ + if( hasWaveForm ){ + for( unsigned int wi = 0; wi < nSample/2; wi++){ + nw = nw +1 ; word = ReadBuffer(nw, verbose-2); + ///The CAEN manual is wrong, the bit [31:16] is anaprobe 1 + bool isTrigger1 = (( word >> 31 ) & 0x1 ); + bool dp1 = (( word >> 30 ) & 0x1 ); + unsigned short wave1 = (( word >> 16) & 0x3FFF); + short trace1 = 0; + if( wave1 & 0x2000){ + trace1 = static_cast(~wave1 + 1 + 0x3FFF); + trace1 = - trace1; + }else{ + trace1 = static_cast(wave1); + } + + ///The CAEN manual is wrong, the bit [31:16] is anaprobe 2 + bool isTrigger0 = (( word >> 15 ) & 0x1 ); + bool dp0 = (( word >> 14 ) & 0x1 ); + unsigned short wave0 = ( word & 0x3FFF); + short trace0 = 0; + if( wave0 & 0x2000){ + trace0 = static_cast(~wave0 + 1 + 0x3FFF); + trace0 = - trace0; + }else{ + trace0 = static_cast(wave0); + } + + if( hasDualTrace ){ + tempWaveform1.push_back(trace1); + tempWaveform2.push_back(trace0); + tempDigiWaveform1.push_back(dp1); + tempDigiWaveform2.push_back(dp0); + }else{ + tempWaveform1.push_back(trace1); + tempWaveform1.push_back(trace0); + tempDigiWaveform1.push_back(dp1); + tempDigiWaveform1.push_back(dp0); + } + + if( isTrigger0 == 1 ) triggerAtSample = 2*wi ; + if( isTrigger1 == 1 ) triggerAtSample = 2*wi + 1; + + if( verbose >= 4 ){ + if( !hasDualTrace ){ + printf("%4d| %5d, %d, %d \n", 2*wi, trace0, dp0, isTrigger0); + printf("%4d| %5d, %d, %d \n", 2*wi+1, trace1, dp1, isTrigger1); + }else{ + printf("%4d| %5d, %5d | %d, %d | %d %d\n", wi, trace0, trace1, dp0, dp1, isTrigger0, isTrigger1); + } + } + } + } + } + unsigned long long extTimeStamp = 0; + unsigned int extra2 = 0; + if( hasExtra2 ){ + nw = nw +1 ; word = ReadBuffer(nw, verbose); + extra2 = word; + if( extra2Option == 0 || extra2Option == 2 ) extTimeStamp = (extra2 >> 16); + } + + unsigned long long timeStamp = (extTimeStamp << 31) ; + timeStamp = timeStamp + timeStamp0; + + if( verbose >= 2 && hasExtra2 ) printf("extra2 : 0x%0X, TimeStamp : %llu\n", extra2, timeStamp); + nw = nw +1 ; word = ReadBuffer(nw, verbose); + unsigned int extra = (( word >> 16) & 0x3FF); + unsigned int energy = (word & 0x7FFF); + bool rollOver = (extra & 0x002); + bool pileUp = (extra & 0x200); + bool pileUpOrRollOver = ((word >> 15) & 0x1); + + if( verbose >= 3 ) { + printf("PileUp or RollOver : %d\n", pileUpOrRollOver); + printf("PileUp : %d , extra : 0x%03x, energy : %d \n", pileUp, extra, energy); + printf(" lost event : %d \n", ((extra >> 0) & 0x1) ); + printf(" roll-over : %d (is fake event ?)\n", ((extra >> 1) & 0x1) ); + printf(" fake-event : %d \n", ((extra >> 3) & 0x1) ); + printf(" input sat. : %d \n", ((extra >> 4) & 0x1) ); + printf(" lost trg : %d \n", ((extra >> 5) & 0x1) ); + printf(" tot trg : %d \n", ((extra >> 6) & 0x1) ); + printf(" coincident : %d \n", ((extra >> 7) & 0x1) ); + printf(" not coin. : %d \n", ((extra >> 8) & 0x1) ); + printf(" pile-up : %d \n", ((extra >> 9) & 0x1) ); + printf(" trapezoid sat. : %d \n", ((extra >> 10) & 0x1) ); + } + + + if( rollOver == 0 ) { // non-time roll over fake event + DataIndex[channel] ++; + if( DataIndex[channel] >= dataSize ) { + LoopIndex[channel] ++; + DataIndex[channel] = 0; + } + + Energy[channel][DataIndex[channel]] = energy; + Timestamp[channel][DataIndex[channel]] = timeStamp * tick2ns; + if(extra2Option == 2 ) fineTime[channel][DataIndex[channel]] = (extra2 & 0x03FF ); + PileUp[channel][DataIndex[channel]] = pileUp; + NumEventsDecoded[channel] ++; + + if( !pileUp ) { + NumNonPileUpDecoded[channel] ++; + TotNumNonPileUpEvents[channel] ++; + } + + if( !fastDecode && hasWaveForm) { + if( hasDualTrace ){ + Waveform1[channel][DataIndex[channel]] = tempWaveform1; + Waveform2[channel][DataIndex[channel]] = tempWaveform2; + }else{ + Waveform1[channel][DataIndex[channel]] = tempWaveform1; + } + DigiWaveform1[channel][DataIndex[channel]] = tempDigiWaveform1; + } + } + + //if( DataIndex[channel] > dataSize ) ClearData(); // if any channel has more data then dataSize, clear all stored data + + if( verbose >= 1 ) printf("evt %4d(%2d) | ch : %2d, PileUp : %d , energy : %5d, rollOver: %d, timestamp : %16llu (%10llu), triggerAt : %d, nSample : %d, %f sec\n", + DataIndex[channel], LoopIndex[channel], channel, pileUp, energy, rollOver, timeStamp * tick2ns, timeStamp, triggerAtSample, nSample , timeStamp * 4. / 1e9); + + } + + ///=========== Key information + /// ch, energy, timestamp + /// trace + + return nw; +} + +//*================================================= +inline int Data::DecodePSDDualChannelBlock(unsigned int ChannelMask, bool fastDecode, int verbose){ + + //printf("======= %s\n", __func__); + + //nw = nw + 1; + unsigned int word = ReadBuffer(nw, verbose); + + if( (word >> 31) != 1 ) return 0; + + unsigned int aggSize = ( word & 0x3FFFFF ) ; + if( verbose >= 2 ) printf(" size : %d \n", aggSize); + + unsigned int nEvents = 0; + nw = nw + 1; word = ReadBuffer(nw, verbose); + unsigned int nSample = ( word & 0xFFFF ) * 8; + unsigned int digitalProbe1 = ( (word >> 16 ) & 0x7 ); + unsigned int digitalProbe2 = ( (word >> 19 ) & 0x7 ); + unsigned int analogProbe = ( (word >> 22 ) & 0x3 ); + unsigned int extraOption = ( (word >> 24 ) & 0x7 ); + bool hasWaveForm = ( (word >> 27 ) & 0x1 ); + bool hasExtra = ( (word >> 28 ) & 0x1 ); + bool hasTimeStamp = ( (word >> 29 ) & 0x1 ); + bool hasCharge = ( (word >> 30 ) & 0x1 ); + bool hasDualTrace = ( (word >> 31 ) & 0x1 ); + + if( verbose >= 2 ) { + printf("dualTrace : %d, Charge : %d, Time: %d, Wave : %d, Extra: %d\n", + hasDualTrace, hasCharge, hasTimeStamp, hasWaveForm, hasExtra); + if( hasExtra ){ + printf(".... extra : "); + switch(extraOption){ + case 0: printf("[0:15] baseline * 4 [16:31] Extended timestamp (16-bit)\n"); break; + case 1: printf("[0:11] reserved [12] lost trigger counted [13] 1024 trigger counted [14] Over-range\n"); + printf("[15] trigger lost [16:31] Extended timestamp (16-bit)\n"); break; + case 2: printf("[0:9] Fine time stamp [10:15] flag [10:15] Reserved [16:31] Extended timestamp (16-bit)\n"); break; + case 3: printf("Reserved\n"); break; + case 4: printf("[0:15] Total trigger counter [16:31] Lost trigger counter\n"); break; + case 5: printf("[0:15] Event after Zero crossing [16:31] Event before Zero crossing\n"); break; + case 6: printf("Reserved\n"); break; + case 7: printf("debug, must be 0x12345678\n"); break; + } + } + if( hasWaveForm ){ + printf(".... digital Probe 1 : "); + switch(digitalProbe1){ + case 0 : printf("Long gate \n"); break; + case 1 : printf("Over threshold \n"); break; + case 2 : printf("Shaped TRG \n"); break; + case 3 : printf("TRG Val. Acceptance \n"); break; + case 4 : printf("Pile-Up \n"); break; + case 5 : printf("Coincidence \n"); break; + case 6 : printf("Reserved \n"); break; + case 7 : printf("Trigger \n"); break; + } + printf(".... digital Probe 2 : "); + switch(digitalProbe2){ + case 0 : printf("Short gate \n"); break; + case 1 : printf("Over threshold \n"); break; + case 2 : printf("TRG Validation \n"); break; + case 3 : printf("TRG HoldOff \n"); break; + case 4 : printf("Pile-Up \n"); break; + case 5 : printf("Coincidence \n"); break; + case 6 : printf("Reserved \n"); break; + case 7 : printf("Trigger \n"); break; + } + printf(".... analog Probe (dual trace : %d): ", hasDualTrace); + if( hasDualTrace ) { + switch(analogProbe){ + case 0 : printf("Input and baseline \n"); break; + case 1 : printf("CFD and baseline \n"); break; + case 2 : printf("Input and CFD \n"); break; + } + }else{ + switch(analogProbe){ + case 0 : printf("Input \n"); break; + case 1 : printf("CFD \n"); break; + } + } + } + + if( !hasExtra && !hasWaveForm) printf("\n"); + + } + + nEvents = (aggSize -2) / (nSample/2 + 2 + hasExtra ); + if( verbose >= 2 ) printf("----------------- nEvents : %d, fast decode : %d\n", nEvents, fastDecode); + + ///========= Decode an event + for( unsigned int ev = 0; ev < nEvents ; ev++){ + if( verbose >= 2 ) printf("--------------------------- event : %d\n", ev); + nw = nw +1 ; word = ReadBuffer(nw, verbose); + bool channelTag = ((word >> 31) & 0x1); + unsigned int timeStamp0 = (word & 0x7FFFFFFF); + int channel = ChannelMask*2 + channelTag; + if( verbose >= 2 ) printf("ch : %d, timeStamp %u \n", channel, timeStamp0); + + ///===== read waveform + if( !fastDecode ) { + tempWaveform1.clear(); + tempWaveform2.clear(); + tempDigiWaveform1.clear(); + tempDigiWaveform2.clear(); + } + + if( fastDecode ){ + nw += nSample/2; + }else{ + if( hasWaveForm ){ + for( unsigned int wi = 0; wi < nSample/2; wi++){ + nw = nw +1 ; word = ReadBuffer(nw, verbose-4); + bool dp2b = (( word >> 31 ) & 0x1 ); + bool dp1b = (( word >> 30 ) & 0x1 ); + unsigned short waveb = (( word >> 16) & 0x3FFF); + + bool dp2a = (( word >> 15 ) & 0x1 ); + bool dp1a = (( word >> 14 ) & 0x1 ); + unsigned short wavea = ( word & 0x3FFF); + + if( hasDualTrace ){ + tempWaveform1.push_back(wavea); + tempWaveform2.push_back(waveb); + }else{ + tempWaveform1.push_back(wavea); + tempWaveform1.push_back(waveb); + } + tempDigiWaveform1.push_back(dp1a); + tempDigiWaveform1.push_back(dp1b); + tempDigiWaveform2.push_back(dp2a); + tempDigiWaveform2.push_back(dp2b); + + if( verbose >= 3 ){ + printf("%4d| %5d, %d, %d \n", 2*wi, wavea, dp1a, dp2a); + printf("%4d| %5d, %d, %d \n", 2*wi+1, waveb, dp1b, dp2b); + } + } + } + } + + unsigned int extra = 0; + unsigned long long extTimeStamp = 0; + + if( hasExtra ){ + nw = nw +1 ; word = ReadBuffer(nw, verbose); + if( verbose > 2 ) printf("extra \n"); + extra = word; + extTimeStamp = 0; + if( extraOption == 0 || extraOption == 2 ) extTimeStamp = (extra >> 16); + } + + unsigned long long timeStamp = (extTimeStamp << 31) ; + timeStamp = timeStamp + timeStamp0; + + nw = nw +1 ; word = ReadBuffer(nw, verbose); + unsigned int Qlong = (( word >> 16) & 0xFFFF); + bool pileup = ((word >> 15) & 0x1); + unsigned int Qshort = (word & 0x7FFF); + bool isEnergyCorrect = ((word >> 15) & 0x1); // the PUR, either pileup or saturated + + if( isEnergyCorrect == 0 ) { + DataIndex[channel] ++; + if( DataIndex[channel] >= dataSize ) { + LoopIndex[channel] ++; + DataIndex[channel] = 0; + } + + Energy2[channel][DataIndex[channel]] = Qshort; + Energy[channel][DataIndex[channel]] = Qlong; + Timestamp[channel][DataIndex[channel]] = timeStamp * tick2ns; + if( extraOption == 2 ) fineTime[channel][DataIndex[channel]] = extra & 0x3FF; + + NumEventsDecoded[channel] ++; + if( !pileup){ + NumNonPileUpDecoded[channel] ++; + TotNumNonPileUpEvents[channel] ++; + } + + if( !fastDecode && hasWaveForm) { + if( hasDualTrace ){ + Waveform1[channel][DataIndex[channel]] = tempWaveform1; + Waveform2[channel][DataIndex[channel]] = tempWaveform2; + }else{ + Waveform1[channel][DataIndex[channel]] = tempWaveform1; + } + DigiWaveform1[channel][DataIndex[channel]] = tempDigiWaveform1; + DigiWaveform2[channel][DataIndex[channel]] = tempDigiWaveform2; + + } + + } + + //if( DataIndex[channel] >= dataSize ) ClearData(); + + //if( verbose >= 2 ) printf("extra : 0x%08x, Qshort : %d, Qlong : %d \n", extra, Qshort, Qlong); + if( verbose == 1 ) printf("ch : %2d, Qshort : %6d, Qlong : %6d, timestamp : %llu\n", + channel, Qshort, Qlong, timeStamp * tick2ns); + if( verbose >= 2 ) printf("Qshort : %6d, Qlong : %6d, timestamp : %llu\n", + Qshort, Qlong, timeStamp * tick2ns); + + + + + } + + ///=========== Key information + /// ch, Qshort, Qlong , timestamp + /// trace + + return nw; +} + +//*================================================= +inline int Data::DecodeQDCGroupedChannelBlock(unsigned int ChannelMask, bool fastDecode, int verbose){ + + //nw = nw + 1; + unsigned int word = ReadBuffer(nw, verbose); + + if( (word >> 31) != 1 ) return 0; + + unsigned int aggSize = ( word & 0x3FFFFF ) ; + if( verbose >= 2 ) printf(" Group agg. size : %d words\n", aggSize); + + unsigned int nEvents = 0; + nw = nw + 1; word = ReadBuffer(nw, verbose); + unsigned int nSample = ( word & 0xFFFF ) * 8; + unsigned int analogProbe = ( (word >> 22 ) & 0x3 ); + bool hasWaveForm = ( (word >> 27 ) & 0x1 ); + bool hasExtra = ( (word >> 28 ) & 0x1 ); + bool hasTimeStamp = ( (word >> 29 ) & 0x1 ); + bool hasEnergy = ( (word >> 30 ) & 0x1 ); + if( (word >> 31 ) != 0 ) return 0; + + if( verbose >= 2 ) { + printf("Charge : %d, Time: %d, Wave : %d, Extra: %d\n", hasEnergy, hasTimeStamp, hasWaveForm, hasExtra); + if( hasWaveForm ){ + printf(".... analog Probe (%d): ", analogProbe); + switch(analogProbe){ + case 0 : printf("Input\n"); break; + case 1 : printf("Smoothed Input\n"); break; + case 2 : printf("Baseline\n"); break; + } + } + } + + nEvents = (aggSize -2) / (nSample/2 + 2 + hasExtra ); + if( verbose >= 2 ) printf("----------------- nEvents : %d, fast decode : %d\n", nEvents, fastDecode); + + ///========= Decode an event + for( unsigned int ev = 0; ev < nEvents ; ev++){ + if( verbose >= 2 ) printf("--------------------------- event : %d\n", ev); + nw = nw +1 ; word = ReadBuffer(nw, verbose); + unsigned int timeStamp0 = (word & 0xFFFFFFFF); + if( verbose >= 2 ) printf("timeStamp %u \n", timeStamp0); + + ///===== read waveform + if( !fastDecode && hasWaveForm ) { + tempWaveform1.clear(); + tempDigiWaveform1.clear(); + tempDigiWaveform2.clear(); + tempDigiWaveform3.clear(); + tempDigiWaveform4.clear(); + } + + if( fastDecode ){ + nw += nSample/2; + }else{ + if( hasWaveForm ){ + for( unsigned int wi = 0; wi < nSample/2; wi++){ + nw = nw +1 ; word = ReadBuffer(nw, verbose-4); + + tempWaveform1.push_back(( word & 0xFFF)); + tempWaveform1.push_back((( word >> 16) & 0xFFF)); + + tempDigiWaveform1.push_back((( word >> 12 ) & 0x1 )); //Gate + tempDigiWaveform1.push_back((( word >> 28 ) & 0x1 )); + + tempDigiWaveform2.push_back((( word >> 13 ) & 0x1 )); //Trigger + tempDigiWaveform2.push_back((( word >> 29 ) & 0x1 )); + + tempDigiWaveform3.push_back((( word >> 14 ) & 0x1 )); //Triger Hold Off + tempDigiWaveform3.push_back((( word >> 30 ) & 0x1 )); + + tempDigiWaveform4.push_back((( word >> 15 ) & 0x1 )); //Over-Threshold + tempDigiWaveform4.push_back((( word >> 31 ) & 0x1 )); + + if( verbose >= 3 ){ + printf("%4d| %5d, %d, %d, %d, %d \n", 2*wi, (word & 0xFFF) , (( word >> 12 ) & 0x1 ), (( word >> 13 ) & 0x1 ), (( word >> 14 ) & 0x1 ), (( word >> 15 ) & 0x1 )); + printf("%-22s", ""); + printf("%4d| %5d, %d, %d, %d, %d \n", 2*wi+1, (( word >> 16) & 0xFFF), (( word >> 28 ) & 0x1 ), (( word >> 29 ) & 0x1 ), (( word >> 30 ) & 0x1 ), (( word >> 31 ) & 0x1 )); + } + } + } + } + + unsigned long long extTimeStamp = 0; + unsigned int baseline = 0; + unsigned long extra = 0; + if( hasExtra ){ + nw = nw +1 ; word = ReadBuffer(nw, verbose); + extra = word; + extTimeStamp = (word & 0xFFF); + baseline = (word >> 16) / 16; + if( verbose >= 2 ) printf("extra : 0x%lx, baseline : %d\n", extra, baseline); + } + + unsigned long long timeStamp = (extTimeStamp << 32) ; + timeStamp = timeStamp + timeStamp0; + + nw = nw +1 ; word = ReadBuffer(nw, verbose); + unsigned int energy = ( word & 0xFFFF); + bool pileup = ((word >> 27) & 0x1); + bool OverRange = ((word >> 26)& 0x1); + unsigned short subCh = ((word >> 28)& 0xF); + + unsigned short channel = ChannelMask*8 + subCh; + + DataIndex[channel] ++; + if( DataIndex[channel] >= dataSize ) { + LoopIndex[channel] ++; + DataIndex[channel] = 0; + } + + Energy[channel][DataIndex[channel]] = energy; + Timestamp[channel][DataIndex[channel]] = timeStamp * tick2ns; + + NumEventsDecoded[channel] ++; + if( !pileup && !OverRange){ + NumNonPileUpDecoded[channel] ++; + TotNumNonPileUpEvents[channel] ++; + } + + if( !fastDecode && hasWaveForm) { + Waveform1[channel][DataIndex[channel]] = tempWaveform1; + DigiWaveform1[channel][DataIndex[channel]] = tempDigiWaveform1; + DigiWaveform2[channel][DataIndex[channel]] = tempDigiWaveform2; + DigiWaveform3[channel][DataIndex[channel]] = tempDigiWaveform3; + DigiWaveform4[channel][DataIndex[channel]] = tempDigiWaveform4; + } + + if( verbose == 1 ) printf("ch : %2d, energy : %d, timestamp : %llu\n", channel, energy, timeStamp * tick2ns); + if( verbose > 1 ) printf("ch : %2d, energy : %d, timestamp : %llu, pileUp : %d, OverRange : %d\n", channel, energy, timeStamp * tick2ns, pileup, OverRange); + + if( verbose == 1) printf("Decoded : %d, total : %ld \n", NumEventsDecoded[channel], TotNumNonPileUpEvents[channel]); + } + + + return nw; + +} + + +#endif diff --git a/Armory/Hit.h b/Armory/Hit.h new file mode 100644 index 0000000..1683ef4 --- /dev/null +++ b/Armory/Hit.h @@ -0,0 +1,52 @@ +#ifndef Hit_H +#define Hit_H + +#include + +class Hit{ +public: + unsigned short sn; + uint8_t ch; + unsigned short energy; + unsigned short energy2; + unsigned long long timestamp; + unsigned short fineTime; + bool pileUp; + + unsigned short traceLength; + std::vector trace; + + Hit(){ + Clear(); + } + + void Clear(){ + sn = 0; + ch = 0; + energy = 0; + energy2 = 0; + timestamp = 0; + fineTime = 0; + traceLength = 0; + pileUp = false; + trace.clear(); + } + + void Print(){ + printf("(%5d, %2d) %6d %16llu, %6d, %d, %5ld\n", sn, ch, energy, timestamp, fineTime, pileUp, trace.size()); + } + + void PrintTrace(){ + for( unsigned short i = 0; i < traceLength; i++){ + printf("%3u | %6d \n", i, trace[i]); + } + } + + // Define operator< for sorting + bool operator<(const Hit& other) const { + return timestamp < other.timestamp; + } + +}; + +#endif \ No newline at end of file diff --git a/Armory/Makefile b/Armory/Makefile index 9cc4957..2ff7b6f 100644 --- a/Armory/Makefile +++ b/Armory/Makefile @@ -27,6 +27,6 @@ Mapper : Mapper.cpp ../mapping.h ClassDet.h # @echo "--------- making ANASEN Monte Carlo" # $(CC) $(COPTS) -o AnasenMS anasenMS.cpp $(ROOTLIBS) -EventBuilder : EventBuilder.cpp ../ClassData.h fsuReader.h ../Hit.h +EventBuilder : EventBuilder.cpp ClassData.h fsuReader.h Hit.h @echo "--------- making EventBuilder" $(CC) $(COPTS) -o EventBuilder EventBuilder.cpp $(ROOTLIBS) diff --git a/Armory/fsuReader.h b/Armory/fsuReader.h new file mode 100644 index 0000000..22ff0de --- /dev/null +++ b/Armory/fsuReader.h @@ -0,0 +1,795 @@ +#include "ClassData.h" +#include "Hit.h" +#include +#include + +// #include "AggSeparator.h" + +class FSUReader{ + + public: + FSUReader(); + FSUReader(std::string fileName, uInt dataSize = 100, int verbose = 1); + FSUReader(std::vector fileList, uInt dataSize = 100, int verbose = 1); + ~FSUReader(); + + void OpenFile(std::string fileName, uInt dataSize, int verbose = 1); + bool IsOpen() const{return inFile == nullptr ? false : true;} + bool IsEndOfFile() const { + // printf("%s : %d | %ld |%ld\n", __func__, feof(inFile), ftell(inFile), inFileSize); + if(fileList.empty() ) { + if( (uLong )ftell(inFile) >= inFileSize){ + return true; + }else{ + return false; + } + }else{ + if( fileID + 1 == (int) fileList.size() && ((uLong)ftell(inFile) >= inFileSize) ) { + return true; + }else{ + return false; + } + } + } + + void ScanNumBlock(int verbose = 1, uShort saveData = 0); // saveData = 0 (no save), 1 (no trace), 2 (with trace); + int ReadNextBlock(bool traceON = false, int verbose = 0, uShort saveData = 0); // saveData = 0 (no save), 1 (no trace), 2 (with trace); + int ReadBlock(unsigned int ID, int verbose = 0); + + unsigned int GetFilePos() const {return filePos;} + unsigned long GetTotNumBlock() const{ return totNumBlock;} + std::vector GetBlockTimestamp() const {return blockTimeStamp;} + + Data * GetData() const{return data;} + + std::string GetFileName() const{return fileName;} + int GetDPPType() const{return DPPType;} + int GetSN() const{return sn;} + int GetTick2ns() const{return tick2ns;} + int GetNumCh() const{return numCh;} + int GetFileOrder() const{return order;} + int GetChMask() const{return chMask;} + unsigned long GetFileByteSize() const {return inFileSize;} + + void ClearHitList() { hit.clear();} + ulong GetHitListLength() const {return hit.size();} + std::vector GetHitVector() const {return hit;} + void SortHit(int verbose = false); + Hit GetHit(int id) const { + if( id < 0 ) id = hit.size() + id; + return hit[id]; + } + + void ClearHitCount() {hitCount = 0;} + ulong GetHitCount() const{return hitCount;} + + std::vector ReadBatch(unsigned int batchSize = 1000000, bool verbose = false); // output the sorted Hit + + // std::string SaveHit(std::vector hitList, bool isAppend = false); + // std::string SaveHit2NewFile(std::string saveFolder = "./", std::string indexStr = ""); + // void SortAndSaveTS(unsigned int batchSize = 1000000, bool verbose = false); + // off_t GetTSFileSize() const {return tsFileSize;} + + //TODO + //void SplitFile(unsigned long hitSizePreFile); + + void PrintHit(ulong numHit = -1, ulong startIndex = 0) { + for( ulong i = startIndex; i < std::min(numHit, hitCount); i++){ + printf("%10zu ", i); hit[i].Print(); + } + } + + static void PrintHitListInfo(std::vector * hitList, std::string name){ + size_t n = hitList->size(); + size_t s = sizeof(Hit); + printf("============== %s, size : %zu | %.2f MByte\n", name.c_str(), n, n*s/1024./1024.); + if( n > 0 ){ + printf("t0 : %15llu ns\n", hitList->front().timestamp); + printf("t1 : %15llu ns\n", hitList->back().timestamp); + printf("dt : %15.3f ms\n", (hitList->back().timestamp - hitList->front().timestamp)/1e6); + } + } + + void PrintHitListInfo(){ + size_t n = hit.size(); + size_t s = sizeof(Hit); + printf("============== reader.hit, size : %zu | %.2f MByte\n", n, n*s/1024./1024.); + if( n > 0 ){ + printf("t0 : %15llu ns\n", hit.at(0).timestamp); + printf("t1 : %15llu ns\n", hit.back().timestamp); + printf("dt : %15.3f ms\n", (hit.back().timestamp - hit.front().timestamp)/1e6); + } + } + + + //void SaveAsCAENCoMPASSFormat(); + + private: + + FILE * inFile; + Data * data; + + std::string fileName; + std::vector fileList; + short fileID; + unsigned long inFileSize; + unsigned int filePos; + unsigned long totNumBlock; + unsigned int blockID; + + bool isDualBlock; + + uShort sn; + uShort DPPType; + uShort tick2ns; + uShort order; + uShort chMask; + uShort numCh; + + std::vector blockPos; + std::vector blockTimeStamp; + + unsigned long hitCount; + + std::vector hit; + + unsigned int word[1]; /// 4 byte + size_t dummy; + char * buffer; + + off_t tsFileSize; + +}; + +inline FSUReader::~FSUReader(){ + delete data; + + if( inFile ) fclose(inFile); + +} + +inline FSUReader::FSUReader(){ + inFile = nullptr; + data = nullptr; + + blockPos.clear(); + blockTimeStamp.clear(); + hit.clear(); + + fileList.clear(); + fileID = -1; + +} + +inline FSUReader::FSUReader(std::string fileName, uInt dataSize, int verbose){ + inFile = nullptr; + data = nullptr; + + blockPos.clear(); + blockTimeStamp.clear(); + hit.clear(); + + fileList.clear(); + fileID = -1; + OpenFile(fileName, dataSize, verbose); +} + +inline FSUReader::FSUReader(std::vector fileList, uInt dataSize, int verbose){ + inFile = nullptr; + data = nullptr; + + blockPos.clear(); + blockTimeStamp.clear(); + hit.clear(); + //The files are the same DPPType and sn + this->fileList = fileList; + fileID = 0; + OpenFile(fileList[fileID], dataSize, verbose); + +} + +inline void FSUReader::OpenFile(std::string fileName, uInt dataSize, int verbose){ + + /// File format must be YYY...Y_runXXX_AAA_BBB_TT_CCC.fsu + /// YYY...Y = prefix + /// XXX = runID, 3 digits + /// AAA = board Serial Number, 3 digits + /// BBB = DPPtype, 3 digits + /// TT = tick2ns, any digits + /// CCC = over size index, 3 digits + + if( inFile != nullptr ) fclose(inFile); + + inFile = fopen(fileName.c_str(), "r"); + + if( inFile == NULL ){ + printf("FSUReader::Cannot open file : %s \n", fileName.c_str()); + this->fileName = ""; + return; + } + + this->fileName = fileName; + + fseek(inFile, 0L, SEEK_END); + inFileSize = ftell(inFile); + if(verbose) printf("%s | file size : %ld Byte = %.2f MB\n", fileName.c_str() , inFileSize, inFileSize/1024./1024.); + fseek(inFile, 0L, SEEK_SET); + filePos = 0; + + if( fileID > 0 ) return; + + totNumBlock = 0; + blockID = 0; + blockPos.clear(); + blockTimeStamp.clear(); + + hitCount = 0; + hit.clear(); + + //check is the file is *.fsu or *.fsu.X + size_t found = fileName.find_last_of('.'); + std::string ext = fileName.substr(found + 1); + + if( ext.find("fsu") != std::string::npos ) { + if(verbose > 1) printf("It is an raw data *.fsu format\n"); + isDualBlock = false; + chMask = -1; + }else{ + chMask = atoi(ext.c_str()); + isDualBlock = true; + if(verbose > 1) printf("It is a splitted dual block data *.fsu.X format, dual channel mask : %d \n", chMask); + } + + std::string fileNameNoExt; + found = fileName.find_last_of(".fsu"); + size_t found2 = fileName.find_last_of('/'); + if( found2 == std::string::npos ){ + fileNameNoExt = fileName.substr(0, found-4); + }else{ + fileNameNoExt = fileName.substr(found2+1, found-4); + } + + // Split the string by underscores + std::istringstream iss(fileNameNoExt); + std::vector tokens; + std::string token; + + while (std::getline(iss, token, '_')) { tokens.push_back(token); } + sn = atoi(tokens[2].c_str()); + tick2ns = atoi(tokens[4].c_str()); + order = atoi(tokens[5].c_str()); + + DPPType = 0; + if( fileName.find("PHA") != std::string::npos ) DPPType = DPPTypeCode::DPP_PHA_CODE; + if( fileName.find("PSD") != std::string::npos ) DPPType = DPPTypeCode::DPP_PSD_CODE; + if( fileName.find("QDC") != std::string::npos ) DPPType = DPPTypeCode::DPP_QDC_CODE; + if( DPPType == 0 ){ + fclose(inFile); + inFile = nullptr; + printf("Cannot find DPPType in the filename. Abort."); + return ; + } + + numCh = (DPPType == DPPTypeCode::DPP_QDC_CODE ? 64 : 16); + + data = new Data(numCh, dataSize); + data->tick2ns = tick2ns; + data->boardSN = sn; + data->DPPType = DPPType; + +} + +inline int FSUReader::ReadNextBlock(bool traceON, int verbose, uShort saveData){ + if( inFile == NULL ) return -1; + if( feof(inFile) || filePos >= inFileSize) { + if( fileID >= 0 && fileID + 1 < (short) fileList.size() ){ + printf("-------------- next file\n"); + fileID ++; + OpenFile(fileList[fileID], data->GetDataSize(), 1 ); + }else{ + return -1; + } + } + + dummy = fread(word, 4, 1, inFile); + fseek(inFile, -4, SEEK_CUR); + + if( dummy != 1) { + printf("fread error, should read 4 bytes, but read %ld x 4 byte, file pos: %ld / %ld byte\n", + dummy, ftell(inFile), inFileSize); + return -10; + } + short header = ((word[0] >> 28 ) & 0xF); + + Hit temp; + + if( header == 0xA ) { ///normal header + + unsigned int aggSize = (word[0] & 0x0FFFFFFF) * 4; ///byte + if( aggSize > inFileSize - ftell(inFile)) aggSize = inFileSize - ftell(inFile); + buffer = new char[aggSize]; + dummy = fread(buffer, aggSize, 1, inFile); + filePos = ftell(inFile); + if( dummy != 1) { + printf("fread error, should read %d bytes, but read %ld x %d byte, file pos: %ld / %ld byte \n", + aggSize, dummy, aggSize, ftell(inFile), inFileSize); + return -30; + } + + data->DecodeBuffer(buffer, aggSize, !traceON, verbose); // data will own the buffer + //printf(" word Index = %u | filePos : %u | ", data->GetWordIndex(), filePos); + + }else if( (header & 0xF ) == 0x8 ) { /// dual channel header + + unsigned int dualSize = (word[0] & 0x7FFFFFFF) * 4; ///byte + buffer = new char[dualSize]; + dummy = fread(buffer, dualSize, 1, inFile); + filePos = ftell(inFile); + + data->buffer = buffer; + data->DecodeDualBlock(buffer, dualSize, DPPType, chMask, !traceON, verbose); + + }else{ + printf("incorrect header.\n trminate."); + return -20; + } + + unsigned int eventCout = 0; + + for( int ch = 0; ch < data->GetNChannel(); ch++){ + if( data->NumEventsDecoded[ch] == 0 ) continue; + + hitCount += data->NumEventsDecoded[ch]; + eventCout += data->NumEventsDecoded[ch]; + + if( saveData ){ + int start = data->GetDataIndex(ch) - data->NumEventsDecoded[ch] + 1; + if( start < 0 ) start = start + data->GetDataSize(); + + for( int i = start; i < start + data->NumEventsDecoded[ch]; i++ ){ + int k = i % data->GetDataSize(); + + temp.sn = sn; + temp.ch = ch; + temp.energy = data->GetEnergy(ch, k); + temp.energy2 = data->GetEnergy2(ch, k); + temp.timestamp = data->GetTimestamp(ch, k); + temp.fineTime = data->GetFineTime(ch, k); + temp.pileUp = data->GetPileUp(ch, k); + if( saveData > 1 ) { + temp.traceLength = data->Waveform1[ch][k].size(); + temp.trace = data->Waveform1[ch][k]; + }else{ + temp.traceLength = 0; + if( temp.trace.size() > 0 ) temp.trace.clear(); + } + + hit.push_back(temp); + } + } + } + + data->ClearTriggerRate(); + data->ClearNumEventsDecoded(); + data->ClearBuffer(); // this will clear the buffer. + return 0; +} + +inline int FSUReader::ReadBlock(unsigned int ID, int verbose){ + if( totNumBlock == 0 )return -1; + if( ID >= totNumBlock )return -1; + + data->ClearData(); + + fseek( inFile, 0L, SEEK_SET); + + if( verbose ) printf("Block index: %u, File Pos: %u byte\n", ID, blockPos[ID]); + + fseek(inFile, blockPos[ID], SEEK_CUR); + filePos = blockPos[ID]; + blockID = ID; + return ReadNextBlock(false, verbose, false); + +} + +inline void FSUReader::SortHit(int verbose){ + if( verbose) printf("\nQuick Sort hit array according to time..."); + std::sort(hit.begin(), hit.end(), [](const Hit& a, const Hit& b) { + return a.timestamp < b.timestamp; + }); + if( verbose) printf(".......done.\n"); +} + +inline void FSUReader::ScanNumBlock(int verbose, uShort saveData){ + if( inFile == nullptr ) return; + if( feof(inFile) ) return; + + blockID = 0; + blockPos.push_back(0); + + data->ClearData(); + rewind(inFile); + filePos = 0; + + bool isTraceOn = saveData < 2 ? false : true; + + while( ReadNextBlock(isTraceOn, verbose - 1, saveData) == 0 ){ + blockPos.push_back(filePos); + blockTimeStamp.push_back(data->aggTime); + blockID ++; + if(verbose && blockID % 10000 == 0) printf("%u, %.2f%% %u/%lu\n\033[A\r", blockID, filePos*100./inFileSize, filePos, inFileSize); + } + + totNumBlock = blockID; + if(verbose) { + printf("\nScan complete: number of data Block : %lu\n", totNumBlock); + printf( " number of hit : %lu", hitCount); + if( hitCount > 1e6 ) printf(" = %.3f million", hitCount/1e6); + printf("\n"); + if( saveData )printf( " size of the hit array : %lu\n", hit.size()); + + if( saveData ){ + size_t sizeT = sizeof(hit[0]) * hit.size(); + printf("size of hit array : %lu byte = %.2f kByte, = %.2f MByte\n", sizeT, sizeT/1024., sizeT/1024./1024.); + } + } + + if( fileList.size() > 0 ){ + fileID = 0; + OpenFile(fileList[fileID], data->GetDataSize(), 0); + } + + rewind(inFile); + blockID = 0; + filePos = 0; + + //check is the hitCount == hit.size(); + if( saveData ){ + if( hitCount != hit.size()){ + printf("!!!!!! the Data::dataSize is not big enough. !!!!!!!!!!!!!!!\n"); + }else{ + SortHit(verbose+1); + } + } +} + +inline std::vector FSUReader::ReadBatch(unsigned int batchSize, bool verbose){ + + // printf("%s sn:%d. filePos : %lu\n", __func__, sn, ftell(inFile)); + + std::vector hitList_A; + if( IsEndOfFile() ) { + hitList_A = hit; + hit.clear(); + return hitList_A; + } + + if( hit.size() == 0 ){ + int res = 0; + do{ + res = ReadNextBlock(true, 0, 3); + }while ( hit.size() < batchSize && res == 0); + SortHit(); + uLong t0_B = hit.at(0).timestamp; + uLong t1_B = hit.back().timestamp; + if( verbose ) { + printf(" hit in memeory : %7zu | %u | %lu \n", hit.size(), filePos, inFileSize); + printf("t0 : %15lu ns\n", t0_B); + printf("t1 : %15lu ns\n", t1_B); + printf("dt : %15.3f ms\n", (t1_B - t0_B)/1e6); + } + + hitList_A = hit; + hit.clear(); + + }else{ + + hitList_A = hit; + hit.clear(); + + } + + if( IsEndOfFile() ) return hitList_A; // when file finished for 1st batch read + + int res = 0; + do{ + res = ReadNextBlock(true, 0, 3); + }while ( hit.size() < batchSize && res == 0); + SortHit(); + uLong t0_B = hit.at(0).timestamp; + uLong t1_B = hit.back().timestamp; + + if( verbose ) { + printf(" hit in memeory : %7zu | %u | %lu \n", hit.size(), filePos, inFileSize); + printf("t0 : %15lu\n", t0_B); + printf("t1 : %15lu\n", t1_B); + printf("dt : %15.3f ms\n", (t1_B - t0_B)/1e6); + } + + uLong t0_A = hitList_A.at(0).timestamp; + uLong t1_A = hitList_A.back().timestamp; + ulong ID_A = 0; + ulong ID_B = 0; + + if( t0_A >= t0_B) { + printf("\033[0;31m!!!!!!!!!!!!!!!!! %s | Need to increase the batch size. \033[0m\n", __func__); + return std::vector (); + } + + if( t1_A > t0_B) { // need to sort between two hitList + + if( verbose ) { + printf("############# need to sort \n"); + printf("=========== sume of A + B : %zu \n", hitList_A.size() + hit.size()); + } + + 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 < hit.size(); j++){ + if( hit[j].timestamp > t1_A ) { + break; + } + hitTemp.push_back(hit[j]); + ID_B = j + 1; + } + + // remove hit elements that is <= t1_A + hit.erase(hit.begin(), hit.begin() + ID_B ); + + // sort hitTemp + std::sort(hitTemp.begin(), hitTemp.end(), [](const Hit& a, const Hit& b) { + return a.timestamp < b.timestamp; + }); + + + if( verbose ) { + printf("----------------- ID_A : %lu, Drop\n", ID_A); + printf("----------------- ID_B : %lu, Drop\n", ID_B); + PrintHitListInfo(&hitList_A, "hitList_A"); + PrintHitListInfo(&hitTemp, "hitTemp"); + PrintHitListInfo(); + printf("=========== sume of A + B + Temp : %zu \n", hitList_A.size() + hit.size() + hitTemp.size()); + printf("----------------- refill hitList_A \n"); + } + + for( size_t j = 0; j < hitTemp.size(); j++){ + hitList_A.push_back(hitTemp[j]); + } + hitTemp.clear(); + + if( verbose ) { + PrintHitListInfo(&hitList_A, "hitList_A"); + PrintHitListInfo(); + printf("=========== sume of A + B : %zu \n", hitList_A.size() + hit.size()); + } + + } + + return hitList_A; + +} + +/* +inline void FSUReader::SortAndSaveTS(unsigned int batchSize, bool verbose){ + + int count = 0; + std::vector hitList_A ; + + do{ + + if( verbose ) printf("***************************************************\n"); + + int res = 0; + do{ + res = ReadNextBlock(true, 0, 3); + }while ( hit.size() < batchSize && res == 0); + + SortHit(); + uLong t0_B = hit.at(0).timestamp; + uLong t1_B = hit.back().timestamp; + + if( verbose ) { + printf(" hit in memeory : %7zu | %u | %lu \n", hit.size(), filePos, inFileSize); + printf("t0 : %15lu\n", t0_B); + printf("t1 : %15lu\n", t1_B); + } + + if( count == 0 ) { + hitList_A = hit; // copy hit + }else{ + + uLong t0_A = hitList_A.at(0).timestamp; + uLong t1_A = hitList_A.back().timestamp; + ulong ID_A = 0; + ulong ID_B = 0; + + if( t0_A > t0_B) { + printf("Need to increase the batch size. \n"); + return; + } + + if( t1_A > t0_B) { // need to sort between two hitList + + if( verbose ) { + printf("############# need to sort \n"); + printf("=========== sume of A + B : %zu \n", hitList_A.size() + hit.size()); + } + + std::vector 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]); + } + + hitList_A.erase(hitList_A.begin() + ID_A, hitList_A.end() ); + if( verbose ) { + printf("----------------- ID_A : %lu, Drop\n", ID_A); + PrintHitListInfo(hitList_A, "hitList_A"); + } + + + for( size_t j = 0; j < hit.size(); j++){ + if( hit[j].timestamp > t1_A ) { + ID_B = j; + break; + } + hitTemp.push_back(hit[j]); + } + + std::sort(hitTemp.begin(), hitTemp.end(), [](const Hit& a, const Hit& b) { + return a.timestamp < b.timestamp; + }); + + hit.erase(hit.begin(), hit.begin() + ID_B ); + + if( verbose ) { + PrintHitListInfo(hitTemp, "hitTemp"); + printf("----------------- ID_B : %lu, Drop\n", ID_B); + PrintHitListInfo(hit, "hit"); + printf("=========== sume of A + B + Temp : %zu \n", hitList_A.size() + hit.size() + hitTemp.size()); + printf("----------------- refill hitList_A \n"); + } + ulong ID_Temp = 0; + for( size_t j = 0; j < hitTemp.size(); j++){ + hitList_A.push_back(hitTemp[j]); + if( hitList_A.size() >= batchSize ) { + ID_Temp = j+1; + break; + } + } + + hitTemp.erase(hitTemp.begin(), hitTemp.begin() + ID_Temp ); + for( size_t j = 0 ; j < hit.size(); j ++){ + hitTemp.push_back(hit[j]); + } + SaveHit(hitList_A, count <= 1 ? false : true); + + if( verbose ) { + PrintHitListInfo(hitList_A, "hitList_A"); + PrintHitListInfo(hitTemp, "hitTemp"); + printf("----------------- replace hitList_A by hitTemp \n"); + } + + hitList_A.clear(); + hitList_A = hitTemp; + hit.clear(); + + if( verbose ) { + PrintHitListInfo(hitList_A, "hitList_A"); + printf("===========================================\n"); + } + + }else{ // save hitList_A, replace hitList_A + + SaveHit(hitList_A, count <= 1? false : true); + hitList_A.clear(); + hitList_A = hit; + if( verbose ) PrintHitListInfo(hitList_A, "hitList_A"); + + } + } + + ClearHitList(); + count ++; + }while(filePos < inFileSize); + + SaveHit(hitList_A, count <= 1 ? false : true); + + printf("================= finished.\n"); +} +*/ + +/* +inline std::string FSUReader::SaveHit(std::vector hitList, bool isAppend){ + + std::string outFileName; + if( fileList.empty() ) { + outFileName = fileName + ".ts" ; + }else{ + outFileName = fileList[0] + ".ts" ; + } + uint64_t hitSize = hitList.size(); + + FILE * outFile ; + if( isAppend ) { + outFile = fopen(outFileName.c_str(), "rb+"); //read/write bineary + + rewind(outFile); + fseek( outFile, 4, SEEK_CUR); + uint64_t org_hitSize; + fread(&org_hitSize, 8, 1, outFile); + + rewind(outFile); + fseek( outFile, 4, SEEK_CUR); + + org_hitSize += hitSize; + + fwrite(&org_hitSize, 8, 1, outFile); + fseek(outFile, 0, SEEK_END); + + }else{ + outFile = fopen(outFileName.c_str(), "wb"); //overwrite binary + uint32_t header = 0xAA000000; + header += sn; + fwrite( &header, 4, 1, outFile ); + fwrite( &hitSize, 8, 1, outFile); + } + + + for( ulong i = 0; i < hitSize; i++){ + + if( i% 10000 == 0 ) printf("Saving %lu/%lu Hit (%.2f%%)\n\033[A\r", i, hitSize, i*100./hitSize); + + uint16_t flag = hitList[i].ch + (hitList[i].pileUp << 8) ; + + if( DPPType == DPPTypeCode::DPP_PSD_CODE ) flag += ( 1 << 15); + if( hitList[i].traceLength > 0 ) flag += (1 << 14); + + // fwrite( &(hit[i].ch), 1, 1, outFile); + fwrite( &flag, 2, 1, outFile); + fwrite( &(hitList[i].energy), 2, 1, outFile); + if( DPPType == DPPTypeCode::DPP_PSD_CODE ) fwrite( &(hitList[i].energy2), 2, 1, outFile); + fwrite( &(hitList[i].timestamp), 6, 1, outFile); + fwrite( &(hitList[i].fineTime), 2, 1, outFile); + if( hitList[i].traceLength > 0 ) fwrite( &(hitList[i].traceLength), 2, 1, outFile); + + for( uShort j = 0; j < hitList[i].traceLength; j++){ + fwrite( &(hitList[i].trace[j]), 2, 1, outFile); + } + + } + + off_t tsFileSize = ftello(outFile); // unsigned int = Max ~4GB + fclose(outFile); + + printf("Saved to %s, size: ", outFileName.c_str()); + if( tsFileSize < 1024 ) { + printf(" %ld Byte", tsFileSize); + }else if( tsFileSize < 1024*1024 ) { + printf(" %.2f kB", tsFileSize/1024.); + }else if( tsFileSize < 1024*1024*1024){ + printf(" %.2f MB", tsFileSize/1024./1024.); + }else{ + printf(" %.2f GB", tsFileSize/1024./1024./1024.); + } + printf("\n"); + + return outFileName; + +} +*/ + + diff --git a/Armory/macro.h b/Armory/macro.h new file mode 100644 index 0000000..d071d78 --- /dev/null +++ b/Armory/macro.h @@ -0,0 +1,56 @@ +#ifndef MACRO_H +#define MACRO_H + +#define MaxNPorts 4 //for optical link +#define MaxNBoards 4 //for both optical link and usb + +#define MaxNDigitizer MaxNPorts * MaxNBoards + +#define MaxRegChannel 16 +#define MaxNChannels 64 +#define MaxRecordLength 0x3fff * 8 +#define MaxSaveFileSize 1024 * 1024 * 1024 * 2 + +#define MaxDisplayTraceTimeLength 20000 //ns +#define ScopeUpdateMiliSec 200 // msec +#define MaxNumberOfTrace 5 // in an event + +#define SETTINGSIZE 2048 + +#define DAQLockFile "DAQLock.dat" +#define PIDFile "pid.dat" + +#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 +inline 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(currentTime.time_since_epoch()); + return nanoseconds.count(); +} + +typedef unsigned short uShort; +typedef unsigned int uInt; +typedef unsigned long uLong; +typedef unsigned long long ullong; + +#define DebugMode 0 //process check, when 1, print out all function call + +// if DebugMode is 1, define DebugPrint() to be printf(), else, DebugPrint() define nothing +#if DebugMode +#define DebugPrint(fmt, ...) printf(fmt "::%s\n",##__VA_ARGS__, __func__); +#else +#define DebugPrint(fmt, ...) +#endif + + +#endif diff --git a/BatchProcess.sh b/BatchProcess.sh new file mode 100644 index 0000000..e781b1b --- /dev/null +++ b/BatchProcess.sh @@ -0,0 +1,6 @@ +#!/bin/bash +#parallel -j 6 echo ./ProcessRun.sh {1} 2000 0 ::: {020..400} + +#parallel --results log/log_{}.txt --ctag -j 6 ./ProcessRun.sh {1} 2000 0 ::: {020..400} # for 17F + +parallel --results log/log_{}.txt --ctag -j 6 ./ProcessRun.sh {1} 2000 0 ::: {001..021} diff --git a/ProcessRun.sh b/ProcessRun.sh index 64ce829..33f9df2 100755 --- a/ProcessRun.sh +++ b/ProcessRun.sh @@ -7,22 +7,22 @@ if [ "$#" -ne 3 ]; then exit 1 fi -runID=$1 +runID=$(printf "%03d" $1) timeWindow=$2 option=$3 # rawFolder=/home/tandem/data1/2024_09_17Fap/data -rawFolder=../Raw_data -rootFolder=../root_data +rawFolder=/mnt/d/17F +rootFolder=/mnt/d/Remapped_files/17F_data/root_data if [ $option -eq 0 ]; then # rsync -auh --info=progress2 splitpole@128.186.111.223:/media/nvmeData/2024_09_17Fap/*.fsu /home/tandem/data1/2024_09_17Fap/data - fileList=`\ls -1 ${rawFolder}/*Run_${runID}_*.fsu` + fileList=`\ls -1 ${rawFolder}/*SourceRun_${runID}_*.fsu` - # ./EventBuilder ${timeWindow} 0 0 100000000 ${fileList} + ./EventBuilder ${timeWindow} 0 0 100000000 ${fileList} outFile=${rawFolder}/*${runID}*${timeWindow}.root @@ -31,4 +31,4 @@ if [ $option -eq 0 ]; then ./Mapper ${rootFolder}/*${runID}*${timeWindow}.root fi -root "processRun.C(\"${rootFolder}/Run_${runID}_mapped.root\")" +# root "processRun.C(\"${rootFolder}/Run_${runID}_mapped.root\")" diff --git a/process_mapped_run.sh b/process_mapped_run.sh index 29f3827..7c67c41 100755 --- a/process_mapped_run.sh +++ b/process_mapped_run.sh @@ -3,7 +3,7 @@ # ========================================== # CONFIGURATION # ========================================== -DATA_DIR="/mnt/d/Remapped_files/27Al_data/root_data" +DATA_DIR="/mnt/d/Remapped_files/17F_data/root_data" MACRO="TrackRecon.C" # SAFETY SETTINGS @@ -49,7 +49,7 @@ for (( i=$START_RUN; i<=$END_RUN; i++ )) do # Construct the input filename # Logic: Run_0 + number -> Run_0115 - file="${DATA_DIR}/Run_0${i}_mapped.root" + file="${DATA_DIR}/Run_${i}_mapped.root" # ------------------------------------------------------------ # SKIP LOGIC