// ----------------------------------------------------------------------------- // ----- TTofTrbTdcUnpacker source file ----- // ----- ----- // ----- created by C. Simon on 2014-04-03 ----- // ----- ----- // ----- based on TTofVftxUnpacker by P.-A. Loizeau ----- // ----- https://subversion.gsi.de/fairroot/cbmroot/development/ploizeau/ ----- // ----- main/unpack/tof/tdc/vftx/TTofVftxUnpacker.cxx ----- // ----- revision 20754, 2013-07-17 ----- // ----------------------------------------------------------------------------- #include "TTofTrbTdcUnpacker.h" // Parameter header #include "TMbsUnpackTofPar.h" // Output data objects #include "TTofTrbTdcBoard.h" // Defines #include "TofDef.h" #include "TofTdcDef.h" // TDC iterator #include "HadaqTdcIterator.h" // ROOT #include "TClonesArray.h" #include "TH1.h" #include "TROOT.h" // FairRoot #include "FairRootManager.h" #include "FairLogger.h" ClassImp(TTofTrbTdcUnpacker) std::map TTofTrbTdcUnpacker::fmRingBufferOverflow; TTofTrbTdcUnpacker::TTofTrbTdcUnpacker( TMbsUnpackTofPar * parIn ): fParUnpack( parIn ), fuNbActiveTrbTdc( parIn->GetNbActiveBoards( tofMbs::trbtdc ) ), fbCalibTrigger(kFALSE), fbJointEdgesChannel( parIn->IsTrbTdcJointEdgesChannel() ), fTrbTdcBoardCollection(0), fTrbTdcRingBufferOverflow(NULL), fTrbTdcChannelOccupancy(), fTrbTdcChannelFineTimeOvershoot(), fTrbTdcChannelUnprocessedHits(), fTrbTdcChannelFineTime(), fTrbTdcChannelCoarseTime() { LOG(INFO)<<"**** TTofTrbTdcUnpacker: Call TTofTrbTdcUnpacker()..."<GetObject("TofTrbTdc"); if(0 == fTrbTdcBoardCollection) { LOG(WARNING)<<"TTofTrbTdcUnpacker::TTofTrbTdcUnpacker : no TOF TRB-TDC array! "<Data(uTdcDataIndex); UInt_t uTdcAddress = uTdcData & 0xffff; UInt_t uNbTdcDataWords = (uTdcData >> 16) & 0xffff; Int_t iTdcBoardIndex = fParUnpack->GetActiveTrbTdcIndex( uTdcAddress ); TTofTrbTdcBoard* tTrbTdcBoard = (TTofTrbTdcBoard*) fTrbTdcBoardCollection->ConstructedAt( iTdcBoardIndex ); tTrbTdcBoard->SetInvalid(); UInt_t uTdcWordCount = 0; // PAL 23/07/2015: Use direct constructor call instead of copy constructor // hadaq::TdcIterator tTrbTdcIterator = hadaq::TdcIterator(); hadaq::TdcIterator tTrbTdcIterator; tTrbTdcIterator.assign(tSubevent, uTdcDataIndex+1, uNbTdcDataWords); hadaq::TdcMessage& tTrbTdcMessage = tTrbTdcIterator.msg(); Bool_t bPreviousIsEpoch = kFALSE; UInt_t uPreviousChannel = 0; while ( tTrbTdcIterator.next() ) { uTdcWordCount++; if( 1 == uTdcWordCount ) { if ( tTrbTdcMessage.isHeaderMsg() ) { if( tTrbTdcMessage.getHeaderErr() ) { tTrbTdcBoard->SetChannelBufferIssue(); fmRingBufferOverflow[iTdcBoardIndex] = kTRUE; // LOG(ERROR)<= tTrbTdcMessage.getTimeTmFine() ) { ( tTrbTdcBoard->GetRefChannelData() ).SetData( tTrbTdcMessage.getTimeChannel(), tTrbTdcMessage.getTimeTmFine(), ( UInt_t )( tTrbTdcIterator.getMsgStamp() & ( trbtdc::kiCoarseCounterSize-1 ) ), 0, tTrbTdcMessage.getTimeEdge() ); ( tTrbTdcBoard->GetRefChannelData() ).SetEpoch( tTrbTdcIterator.getCurEpoch() ); ( tTrbTdcBoard->GetRefChannelData() ).SetFullCoarseTime( tTrbTdcIterator.getMsgStamp() ); tTrbTdcBoard->SetTriggerTime( ( tTrbTdcBoard->GetRefChannelData() ).GetCoarseTime() ); } else { LOG(ERROR)<GetChannelNb() < uChNumber ) ) { LOG(ERROR)<AddData( tValidHit ); continue; } } break; } case trbtdc::message_Epoch: LOG(ERROR)<GetChannelNb() < uChNumber ) ) { LOG(ERROR)<AddData( tValidHit ); continue; } } break; } case trbtdc::message_Epoch: bPreviousIsEpoch = kTRUE; continue; break; default: continue; break; } } } tTrbTdcBoard->SortData(); tTrbTdcBoard->SetCalibData(fbCalibTrigger); tTrbTdcBoard->SetValid(); LOG(DEBUG)<cd(); // <= To prevent histos from being sucked in by the param file of the TRootManager ! TH1* hTemp = 0; fTrbTdcChannelFineTime.resize( fuNbActiveTrbTdc ); fTrbTdcChannelCoarseTime.resize( fuNbActiveTrbTdc ); for( UInt_t uBoardIndex = 0; uBoardIndex < fuNbActiveTrbTdc; uBoardIndex++) { UInt_t uTrbNetAddress = fParUnpack->GetActiveTrbTdcAddr(uBoardIndex); // Board specific histograms hTemp = new TH1I( Form("tof_%s_ch_occ_%03u", toftdc::ksTdcHistName[ toftdc::trb ].Data(), uBoardIndex), Form("Channel occupancy in TRB-TDC #%03u (0x%04x)", uBoardIndex, uTrbNetAddress), trbtdc::kuNbChan+1, 0.0, trbtdc::kuNbChan+1 ); fTrbTdcChannelOccupancy.push_back( hTemp ); hTemp = new TH1I( Form("tof_%s_ch_highft_%03u", toftdc::ksTdcHistName[ toftdc::trb ].Data(), uBoardIndex), Form("Fine time overshoot in TRB-TDC #%03u (0x%04x)", uBoardIndex, uTrbNetAddress), trbtdc::kuNbChan+1, 0.0, trbtdc::kuNbChan+1 ); fTrbTdcChannelFineTimeOvershoot.push_back( hTemp ); hTemp = new TH1I( Form("tof_%s_ch_unproc_%03u", toftdc::ksTdcHistName[ toftdc::trb ].Data(), uBoardIndex), Form("Unprocessed hits in TRB-TDC #%03u (0x%04x)", uBoardIndex, uTrbNetAddress), trbtdc::kuNbChan+1, 0.0, trbtdc::kuNbChan+1 ); fTrbTdcChannelUnprocessedHits.push_back( hTemp ); // Reference Channel specific histograms hTemp = new TH1I( Form("tof_%s_ft_b%03u_ref", toftdc::ksTdcHistName[ toftdc::trb ].Data(), uBoardIndex), Form("Counts per fine-time bin for reference channel on TRB-TDC #%03u (0x%04x)", uBoardIndex, uTrbNetAddress), trbtdc::kiFineCounterSize, -0.5, trbtdc::kiFineCounterSize - 0.5 ); (fTrbTdcChannelFineTime[uBoardIndex]).push_back( hTemp ); hTemp = new TH1I( Form("tof_%s_ct_b%03u_ref", toftdc::ksTdcHistName[ toftdc::trb ].Data(), uBoardIndex), Form("Counts per coarse-time bin for reference channel on TRB-TDC #%03u (0x%04x)", uBoardIndex, uTrbNetAddress), trbtdc::kiCoarseCounterSize/1024/512, -0.5, trbtdc::kiCoarseCounterSize/1024/512 - 0.5 ); // TODO: remove hard coding (fTrbTdcChannelCoarseTime[uBoardIndex]).push_back( hTemp ); for( UInt_t uChannelIndex = 0; uChannelIndex < trbtdc::kuNbChan; uChannelIndex++) { // Channel specific histograms hTemp = new TH1I( Form("tof_%s_ft_b%03u_ch%03u", toftdc::ksTdcHistName[ toftdc::trb ].Data(), uBoardIndex, uChannelIndex), Form("Counts per fine-time bin for channel %3u on TRB-TDC #%03u (0x%04x)", uChannelIndex, uBoardIndex, uTrbNetAddress), trbtdc::kiFineCounterSize, -0.5, trbtdc::kiFineCounterSize - 0.5 ); (fTrbTdcChannelFineTime[uBoardIndex]).push_back( hTemp ); hTemp = new TH1I( Form("tof_%s_ct_b%03u_ch%03u", toftdc::ksTdcHistName[ toftdc::trb ].Data(), uBoardIndex, uChannelIndex), Form("Counts per coarse-time bin for channel %3u on TRB-TDC #%03u (0x%04x)", uChannelIndex, uBoardIndex, uTrbNetAddress), trbtdc::kiCoarseCounterSize/1024/512, -0.5, trbtdc::kiCoarseCounterSize/1024/512 - 0.5 ); // TODO: remove hard coding (fTrbTdcChannelCoarseTime[uBoardIndex]).push_back( hTemp ); } } fTrbTdcRingBufferOverflow = new TH1I( Form("tof_%s_buffer_overflow", toftdc::ksTdcHistName[ toftdc::trb ].Data()), "TRB-TDC ring buffer overflows per board", fuNbActiveTrbTdc, 0, fuNbActiveTrbTdc); gDirectory->cd( oldir->GetPath() ); // <= To prevent histos from being sucked in by the param file of the TRootManager! } void TTofTrbTdcUnpacker::FillHistos() { LOG(DEBUG)<<"**** TTofTrbTdcUnpacker: Call FillHistos()..."<GetActiveTrbTdcAddr(uBoardIndex); tTrbTdcBoard = (TTofTrbTdcBoard*) fTrbTdcBoardCollection->ConstructedAt(uBoardIndex); // Loop over regular channels for( UInt_t uDataIndex = 0; uDataIndex < tTrbTdcBoard->GetDataNb() ; uDataIndex++ ) { TTofTrbTdcData data = tTrbTdcBoard->GetData( uDataIndex ); TString sTemp = Form( " TTofTrbTdcUnpacker::FillHistos: Addr 0x%04x Board #%03u Data #%04u Chan %3d CT %7d FT %7d Edge %1u", uTrbNetAddress, uBoardIndex, uDataIndex, data.GetChannel()+1, data.GetCoarseTime(), data.GetFineTime(), data.GetEdge() ); LOG(DEBUG2)<Fill( data.GetChannel() + 1 ); if( trbtdc::time_FineTimeBitMask == data.GetFineTime() ) { fTrbTdcChannelUnprocessedHits[uBoardIndex]->Fill( data.GetChannel() + 1 ); } if( trbtdc::kuHighestReasonableFineTimeBin < data.GetFineTime() ) { fTrbTdcChannelFineTimeOvershoot[uBoardIndex]->Fill( data.GetChannel() + 1 ); } fTrbTdcChannelFineTime[uBoardIndex][ data.GetChannel() +1 ]->Fill( data.GetFineTime() ); fTrbTdcChannelCoarseTime[uBoardIndex][ data.GetChannel() +1 ]->Fill( data.GetCoarseTime()%2048 ); } // Consider the respective reference channel fTrbTdcChannelOccupancy[uBoardIndex]->Fill(0); if( trbtdc::time_FineTimeBitMask == ( tTrbTdcBoard->GetRefChannelData() ).GetFineTime() ) { fTrbTdcChannelUnprocessedHits[uBoardIndex]->Fill(0); } if( trbtdc::kuHighestReasonableFineTimeBin < ( tTrbTdcBoard->GetRefChannelData() ).GetFineTime() ) { fTrbTdcChannelFineTimeOvershoot[uBoardIndex]->Fill(0); } fTrbTdcChannelFineTime[uBoardIndex][0]->Fill( ( tTrbTdcBoard->GetRefChannelData() ).GetFineTime() ); fTrbTdcChannelCoarseTime[uBoardIndex][0]->Fill( ( tTrbTdcBoard->GetRefChannelData() ).GetCoarseTime()%2048 ); } for ( std::map::iterator it = fmRingBufferOverflow.begin(); it != fmRingBufferOverflow.end(); ++it) { if( it->second ) { fTrbTdcRingBufferOverflow->Fill( it->first ); } } fmRingBufferOverflow.clear(); } void TTofTrbTdcUnpacker::WriteHistos( TDirectory* inDir) { LOG(INFO)<<"**** TTofTrbTdcUnpacker: Call WriteHistos()..."<mkdir( Form( "Unp_%s_%03u", toftdc::ksTdcHistName[ toftdc::trb ].Data(), uBoardIndex) ); cdTrbTdcUnp[uBoardIndex]->cd(); // make the "Unp..." directory the current directory fTrbTdcChannelOccupancy[uBoardIndex]->Write(); fTrbTdcChannelFineTimeOvershoot[uBoardIndex]->Write(); fTrbTdcChannelUnprocessedHits[uBoardIndex]->Write(); for( UInt_t uChannelIndex = 0; uChannelIndex <= trbtdc::kuNbChan; uChannelIndex++) { fTrbTdcChannelFineTime[uBoardIndex][uChannelIndex]->Write(); fTrbTdcChannelCoarseTime[uBoardIndex][uChannelIndex]->Write(); } } TDirectory * tAllHistoDir = inDir->mkdir( Form( "Unp_%s_all", toftdc::ksTdcHistName[ toftdc::trb ].Data()) ); tAllHistoDir->cd(); fTrbTdcRingBufferOverflow->Write(); gDirectory->Cd(oldDir->GetPath()); } void TTofTrbTdcUnpacker::DeleteHistos() { LOG(INFO)<<"**** TTofTrbTdcUnpacker: Call DeleteHistos()..."<