simplify trigger rate calculation

This commit is contained in:
Ryan Tang 2024-02-23 18:31:39 -05:00
parent 8e3dabb3f8
commit 93f89d9264
5 changed files with 91 additions and 113 deletions

View File

@ -45,10 +45,6 @@ class Data{
unsigned int aggTime; /// update every decode
/// store data for event building and deduce the trigger rate.
//it is a circular memory
bool IsNotRollOverFakeAgg;
int GetLoopIndex(unsigned short ch) const {return LoopIndex[ch];}
int GetDataIndex(unsigned short ch) const {return DataIndex[ch];}
@ -78,6 +74,7 @@ class Data{
void ClearDataPointer();
void ClearData();
void ClearTriggerRate();
void ClearNumEventsDecoded();
void ClearBuffer();
unsigned short GetNChannel() const {return numInputCh;}
@ -102,6 +99,9 @@ class Data{
uint64_t GetTotalFileSize() const {return FinishedOutFilesSize + outFileSize;}
void ZeroTotalFileSize() { FinishedOutFilesSize = 0; }
void CalTriggerRate();
void ClearReferenceTime();
protected:
const unsigned short numInputCh;
@ -132,7 +132,9 @@ class Data{
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);
@ -149,14 +151,17 @@ inline Data::Data(unsigned short numCh, uShort dataSize): numInputCh(numCh){
boardSN = 0;
DPPType = DPPType::DPP_PHA_CODE;
DPPTypeStr = "";
IsNotRollOverFakeAgg = false;
buffer = NULL;
AllocateDataSize(dataSize);
for ( int i = 0; i < MaxNChannels; i++) TotNumNonPileUpEvents[i] = 0;
for ( int i = 0; i < MaxNChannels; i++) {
TotNumNonPileUpEvents[i] = 0;
t0[i] = 0;
}
ClearData();
ClearTriggerRate();
ClearNumEventsDecoded();
nw = 0;
outFileIndex = 0;
@ -265,6 +270,11 @@ 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;
}
@ -273,7 +283,6 @@ inline void Data::ClearTriggerRate(){
inline void Data::ClearData(){
nByte = 0;
AllocatedSize = 0;
IsNotRollOverFakeAgg = false;
for( int ch = 0 ; ch < MaxNChannels; ch++){
LoopIndex[ch] = 0;
DataIndex[ch] = -1;
@ -322,6 +331,50 @@ 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(){
for( int ch = 0; ch < numInputCh; ch ++ ){
if( t0[ch] == 0 ) {
TriggerRate[ch] = 0;
NonPileUpRate[ch] = 0;
continue;
}
if( NumEventsDecoded[ch] < dataSize ){
unsigned long long dTime = Timestamp[ch][DataIndex[ch]] - t0[ch];
double sec = dTime / 1e9;
TriggerRate[ch] = (NumEventsDecoded[ch]-1)/sec;
NonPileUpRate[ch] = (NumNonPileUpDecoded[ch]-1)/sec;
}else{
uShort nEvent = 100;
unsigned long long dTime = Timestamp[ch][DataIndex[ch]] - Timestamp[ch][DataIndex[ch] - 100];
double sec = dTime / 1e9;
TriggerRate[ch] = (nEvent-1)/sec;
NonPileUpRate[ch] = (NumNonPileUpDecoded[ch])/sec * (nEvent-1)/(NumEventsDecoded[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;
}
}
//^###############################################
//^############################################### Save fsu file
inline bool Data::OpenSaveFile(std::string fileNamePrefix){
@ -400,10 +453,6 @@ inline void Data::CloseSaveFile(){
inline void Data::PrintStat(bool skipEmpty) {
printf("============================= Print Stat. Digi-%d\n", boardSN);
if( !IsNotRollOverFakeAgg ) {
printf(" this is roll-over fake event or no events.\n");
return;
}
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++){
@ -414,6 +463,7 @@ inline void Data::PrintStat(bool skipEmpty) {
printf("---+--------+-----------+-----------+----------\n");
ClearTriggerRate();
ClearNumEventsDecoded();
}
@ -566,95 +616,11 @@ inline void Data::DecodeBuffer(bool fastDecode, int verbose){
///printf("nw : %d ,x 4 = %d, nByte : %d \n", nw, 4*nw, nByte);
}while(4*nw < nByte);
// bool debug = false;
// if( DPPType == DPPType::DPP_QDC_CODE ) debug = true;
///^===================Calculate trigger rate and first and last Timestamp
for(int ch = 0; ch < MaxNChannels; ch++){
if( ch > numInputCh ) continue;
if( DataIndex[ch] < 0 ) continue;
if( NumEventsDecoded[ch] > 0 ) {
// printf("%s | ch %d | %d %d \n", __func__, ch, LoopIndex[ch], DataIndex[ch]);
IsNotRollOverFakeAgg = true;
}else{
// TriggerRate[ch] = 0;
// NonPileUpRate[ch] = 0;
continue;
}
// if( debug ) printf("Ch : %2d | Decoded Event : %d \n", ch, NumEventsDecoded[ch]);
if( NumEventsDecoded[ch] > 4 ){
int indexStart = DataIndex[ch] - NumEventsDecoded[ch] + 1;
if( indexStart < 0 ) indexStart += dataSize;
unsigned long long dTime = Timestamp[ch][DataIndex[ch]] - Timestamp[ch][indexStart];
double sec = dTime / 1e9;
TriggerRate[ch] = (NumEventsDecoded[ch]-1)/sec;
NonPileUpRate[ch] = (NumNonPileUpDecoded[ch]-1)/sec;
// if( debug ) printf("%d %d| %d %d | %llu, %.3e | %.2f, %.2f\n", indexStart, DataIndex[ch], NumEventsDecoded[ch], NumNonPileUpDecoded[ch], dTime, sec , TriggerRate[ch], NonPileUpRate[ch]);
}else{ // look in to the data in the memory, not just this agg.
const short nEvent = 10;
if( TotNumNonPileUpEvents[ch] >= nEvent ){
calIndexes[ch][1] = DataIndex[ch];
calIndexes[ch][0] = DataIndex[ch] - nEvent + 1;
if (calIndexes[ch][0] < 0 ) calIndexes[ch][0] += dataSize;
// std::vector<unsigned long long> tList ;
// for( int i = 0; i < nEvent ; i ++){
// int j = (calIndexes[ch][0] + i) % dataSize;
// tList.push_back( Timestamp[ch][j]);
// }
// if( DPPType == DPPType::DPP_QDC_CODE){
// //std::sort(tList.begin(), tList.end());
// unsigned long long t0 = tList.front(); // earlier
// unsigned long long t1 = tList.back(); // latest
// for( int i = 0; i < (int) tList.size(); i++){
// if( t0 < tList[i]) t0 = tList[i];
// if( t1 > tList[i]) t1 = tList[i];
// }
// tList.front() = t0;
// tList.back() = t1;
// }
//double sec = ( tList.back() - tList.front() ) * tick2ns / 1e9;
unsigned long long t0 = Timestamp[ch][(calIndexes[ch][0]) % dataSize]; // earlier
unsigned long long t1 = Timestamp[ch][(calIndexes[ch][1]) % dataSize];; // latest
if( t0 > t1 ) {
printf("digi-%d, ch-%d | data is not in time order\n", boardSN, ch);
unsigned long long tt = t1;
t1 = t0;
t0 = tt;
}
double sec = ( t1 - t0 ) * tick2ns / 1e9;
TriggerRate[ch] = nEvent / sec;
short pileUpCount = 0;
for( int i = 0 ; i < nEvent; i++ ) {
int j = (calIndexes[ch][0] + i) % dataSize;
if( PileUp[ch][j] ) pileUpCount ++;
}
NonPileUpRate[ch] = (nEvent - pileUpCount)/sec;
// if( debug ) printf("%2d | %10llu %10llu, %d = %f sec, rate = %f, nEvent %d pileUp %d \n", ch, t1, t0, tick2ns, sec, nEvent / sec, nEvent, pileUpCount);
}
}
//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];
}
}
//*=================================================

View File

@ -483,7 +483,7 @@ void Digitizer::StartACQ(){
if( softwareDisable ) return;
if ( AcqRun ) return;
ret |= CAEN_DGTZ_SetDPPEventAggregation(handle, 0, 0); // Auto set
// ret |= CAEN_DGTZ_SetDPPEventAggregation(handle, 0, 0); // Auto set
unsigned int bufferSize = 0;
if( DPPType == V1730_DPP_PHA_CODE ){
@ -536,6 +536,10 @@ void Digitizer::StartACQ(){
}
AcqRun = true;
data->ClearTriggerRate();
data->ClearData();
printf(" ACQ mode : %s (%d), TRG-OUT mode : %s (%d) \n", acqStr.c_str(), acqID, trgOutStr.c_str(), trgOutID);
ret = CAEN_DGTZ_SWStartAcquisition(handle);
@ -545,8 +549,7 @@ void Digitizer::StartACQ(){
}
printf("\e[1m\e[33m======= Acquisition Started for %d | Board %d, Port %d\e[0m\n", BoardInfo.SerialNumber, boardID, portID);
AcqRun = true;
data->ClearTriggerRate();
}
@ -559,7 +562,9 @@ void Digitizer::StopACQ(){
AcqRun = false;
data->PrintStat();
data->ClearTriggerRate();
data->ClearNumEventsDecoded();
data->ClearBuffer();
data->ClearReferenceTime();
data->ZeroTotalFileSize();
}

View File

@ -340,13 +340,13 @@ void MainWindow::OpenDataPath(){
if( result > 0 ) {
leDataPath->setText(fileDialog.selectedFiles().at(0));
rawDataPath = leDataPath->text();
chkSaveData->setEnabled(true);
}else{
leDataPath->clear();
rawDataPath = "";
chkSaveData->setEnabled(false);
}
if( !rawDataPath.isEmpty() ) chkSaveData->setEnabled(true);
SaveProgramSettings();
LoadLastRunFile();
@ -468,7 +468,7 @@ void MainWindow::LoadProgramSettings(){
if( rawDataDir.mkdir(rawDataPath) ){
LogMsg("Created folder <b>" + rawDataPath + "</b> for storing root files.");
}else{
LogMsg("<font style=\"color:red;\"><b>" + rawDataPath + "</b> cannot be created. Access right problem? </font>" );
LogMsg("<font style=\"color:red;\"><b>" + rawDataPath + "</b> Raw data folder cannot be created. Access right problem? </font>" );
}
}else{
LogMsg("<b>" + rawDataPath + "</b> already exist." );
@ -830,6 +830,7 @@ void MainWindow::SetupScalar(){
lbScalarACQStatus = nullptr;
scalarThread = new TimingThread(scalar);
scalarThread->SetWaitTimeinSec(1.0);
connect(scalarThread, &TimingThread::timeUp, this, &MainWindow::UpdateScalar);
unsigned short maxNChannel = 0;
@ -987,6 +988,7 @@ void MainWindow::UpdateScalar(){
if(digiSettings && digiSettings->isVisible() && digiSettings->GetTabID() == iDigi) digiSettings->UpdateACQStatus(acqStatus);
digiMTX[iDigi].lock();
digi[iDigi]->GetData()->CalTriggerRate();
// printf("### %d ", iDigi);
// digi[iDigi]->GetData()->PrintAllData(true, 10);
if( chkSaveData->isChecked() ) totalFileSize += digi[iDigi]->GetData()->GetTotalFileSize();
@ -995,7 +997,7 @@ void MainWindow::UpdateScalar(){
QString b = "";
if( digi[iDigi]->GetInputChannelOnOff(i) == true ) {
//printf(" %3d %2d | %7.2f %7.2f \n", digi[iDigi]->GetSerialNumber(), i, digi[iDigi]->GetData()->TriggerRate[i], digi[iDigi]->GetData()->NonPileUpRate[i]);
// printf(" %3d %2d | %7.2f %7.2f \n", digi[iDigi]->GetSerialNumber(), i, digi[iDigi]->GetData()->TriggerRate[i], digi[iDigi]->GetData()->NonPileUpRate[i]);
QString a = QString::number(digi[iDigi]->GetData()->TriggerRate[i], 'f', 2);
QString b = QString::number(digi[iDigi]->GetData()->NonPileUpRate[i], 'f', 2);
leTrigger[iDigi][i]->setText(a);
@ -1007,8 +1009,6 @@ void MainWindow::UpdateScalar(){
}
}
digi[iDigi]->GetData()->ClearTriggerRate();
digiMTX[iDigi].unlock();
}
@ -1052,7 +1052,6 @@ void MainWindow::StartACQ(){
readDataThread[i]->SetSaveData(chkSaveData->isChecked());
LogMsg("Digi-" + QString::number(digi[i]->GetSerialNumber()) + " is starting ACQ." );
digi[i]->WriteRegister(DPP::SoftwareClear_W, 1);
digi[i]->GetData()->ClearData();
digi[i]->StartACQ();

View File

@ -98,8 +98,14 @@ if you want to use GDB debugger, in the *.pro file add
There is a folder Aux, this folder contains many auxillary programs, such as EventBuilder. User can `make` under the folder to compile the programs.
# Tested Trigger Rate
* V1725, 1 MHz to 3 ch (decay = 500 ns), no trace. need to set Agg/Read = 1023 and Evt/Agg = 511.
# Known Issues
* Pile up rate is not accurate for very high input rate ( > 60 kHz ).
* When using the scope, the Agg/Read must be smaller than 512.
* Although the Events/Agg used the CAEN API to recalculate before ACQ start, for PHA firmware, when the trigger rate changed, the Events per Agg need to be changed.
* The Agg Organization, Event per Agg, Record Length are strongly correlated. Some settings are invalid and will cause the digitizer goes crazy.
* load digitizer setting would not load everything, only load the channel settings and some board settings.
@ -109,4 +115,4 @@ There is a folder Aux, this folder contains many auxillary programs, such as Eve
# Known Bugs
* There is no known bug. Please report to rtang@fsu.edu if you find one.
* EventBuilder will crash when trigger rate of the data is very high.

View File

@ -369,9 +369,11 @@ void Scope::StartScope(){
traceOn[iDigi] = digi[iDigi]->IsRecordTrace(); //remember setting
SendLogMsg("Digi-" + QString::number(digi[iDigi]->GetSerialNumber()) + " is starting ACQ." );
digi[iDigi]->WriteRegister(DPP::SoftwareClear_W, 1);
digi[iDigi]->GetData()->ClearData();
digi[iDigi]->SetBits(DPP::BoardConfiguration, DPP::Bit_BoardConfig::RecordTrace, 1, -1);
// SendLogMsg("Set Events/Agg to 1 for scope");
// digi[iDigi]->WriteRegister(DPP::NumberEventsPerAggregate_G, 1, -1);
readDataThread[iDigi]->SetScopeMode(true);
readDataThread[iDigi]->SetSaveData(false);
@ -484,7 +486,7 @@ void Scope::UpdateScope(){
if( traceLength * tick2ns * factor > MaxDisplayTraceTimeLength) traceLength = MaxDisplayTraceTimeLength / tick2ns/ factor;
//printf("--- %s| %d, %d, %d | %ld(%d) | %d, %d | %d\n", __func__, ch, data->GetLoopIndex(ch), index, data->Waveform1[ch][index].size(), traceLength, factor, tick2ns, traceLength * tick2ns * factor );
if( index > 0 && data->TriggerRate[ch] > 0 ){
if( index > 0 ){
QVector<QPointF> points[5];
if( digi[ID]->GetDPPType() == V1730_DPP_PHA_CODE ) {