simplify trigger rate calculation
This commit is contained in:
parent
8e3dabb3f8
commit
93f89d9264
166
ClassData.h
166
ClassData.h
|
@ -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];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//*=================================================
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
13
FSUDAQ.cpp
13
FSUDAQ.cpp
|
@ -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();
|
||||
|
||||
|
|
|
@ -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.
|
|
@ -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 ) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user