/** * @file * @author Christian Simon * @since 2017-07-27 */ #include "CbmTofBuildMCEvents.h" #include "CbmEvent.h" #include "CbmLink.h" #include "CbmMatch.h" #include "CbmTofDigiExp.h" #include "CbmTofPoint.h" #include "CbmTofDef.h" #include "FairLogger.h" #include "FairRootManager.h" #include "TClonesArray.h" #include #include // --------------------------------------------------------------------------- CbmTofBuildMCEvents::CbmTofBuildMCEvents() : FairTask("TofBuildMCEvents"), fTofDigis(NULL), fTofPoints(NULL), fEvents(NULL), fiNEvents(0), fbPointsInTS(kFALSE), fbNumberSortEvents(kFALSE) { } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- CbmTofBuildMCEvents::~CbmTofBuildMCEvents() { } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- void CbmTofBuildMCEvents::Exec(Option_t*) { // Clear output array fEvents->Delete(); fiNEvents = 0; std::map eventMap; // If MC points have been inserted into timeslices, make their indices // available in 'CbmEvent' as well. if(fbPointsInTS) { for(Int_t iPoint = 0; iPoint < fTofPoints->GetEntriesFast(); iPoint++) { CbmTofPoint* tPoint = dynamic_cast(fTofPoints->At(iPoint)); Int_t iMCEventNumber = tPoint->GetEventID(); // All MC points available from a MC input file have a non-negative // 'fEventId'. Dark rate points, in contrast, are generated during // digitization and cannot be assigned to an 'event' in the original sense // as they appear on the continous time axis uncorrelated to events // provided by a 'FairSource' instance. Therefore, such points are skipped // here. if(-1 != iMCEventNumber) { CbmEvent* tEvent(NULL); if(eventMap.find(iMCEventNumber) != eventMap.end()) { // The MC event is already known. tEvent = eventMap.at(iMCEventNumber); } else { // The MC event is not known yet. tEvent = new((*fEvents)[fiNEvents++]) CbmEvent(iMCEventNumber); eventMap.emplace(iMCEventNumber, tEvent); LOG(INFO)<AddData(kTofPoint, iPoint); } } } for(Int_t iDigi = 0; iDigi < fTofDigis->GetEntriesFast(); iDigi++) { CbmTofDigiExp* tDigi = dynamic_cast(fTofDigis->At(iDigi)); Int_t iNMCLinks = tDigi->GetMatch()->GetNofLinks(); for(Int_t iLink = 0; iLink < iNMCLinks; iLink++) { const CbmLink& tLink = tDigi->GetMatch()->GetLink(iLink); // Only consider digis that contain at least one contribution from a primary // source signal. // If the digi contains primary signal contributions from more than one // MC event, assign the digi to all MC events found. if(tof::signal_SourcePrimary == tLink.GetUniqueID()) { Int_t iMCEventNumber(-1); if(!fbPointsInTS) { iMCEventNumber = tLink.GetEntry(); } else { // MC reference point is not available in the current TS if(-1 == tLink.GetIndex()) { iMCEventNumber = tLink.GetEntry(); } // MC reference point IS available in the current TS else { CbmTofPoint* tPoint = dynamic_cast(fTofPoints->At(tLink.GetIndex())); iMCEventNumber = tPoint->GetEventID(); } } CbmEvent* tEvent(NULL); if(eventMap.find(iMCEventNumber) != eventMap.end()) { // The MC event is already known. tEvent = eventMap.at(iMCEventNumber); } else { // The MC event is not known yet. tEvent = new((*fEvents)[fiNEvents++]) CbmEvent(iMCEventNumber); eventMap.emplace(iMCEventNumber, tEvent); LOG(INFO)<AddData(kTofDigi, iDigi); } } } // There is a small probability that in case of two events overlapping in time // due to a tiny difference between the sampled event start times an early // digi of the latter event might have a smaller timestamp than the earliest // digi of the former event (particle velocities, digitization effects etc.). // This would result in the 'CbmEvent' objects in the output 'TClonesArray' // not being sorted in increasing order with respect to 'CbmEvent::fNumber', // i.e. the MC event index. For this reason, we sort the "Event" array here. // FIXME: For a timeslice containing about 80,000 events it takes // 'TSeqCollection::QSort' about 2 minutes(!) to sort the "Event" array with // respect to 'CbmEvent::fNumber'. This is not acceptable, so we skip the // sorting as it is not necessary. Timeslice containers should NOT be too // big compared to the mean distance between events! if(fbNumberSortEvents) { fEvents->Sort(); } // It might be useful to know the time that an event spans, i.e. the // time difference between its first and its last digi. for(Int_t iEvent = 0; iEvent < fEvents->GetEntriesFast(); iEvent++) { CbmEvent* tEvent = dynamic_cast(fEvents->At(iEvent)); if(0 < tEvent->GetNofData(kTofDigi)) { CbmTofDigiExp* tFirstDigi = dynamic_cast(fTofDigis->At(tEvent->GetIndex(kTofDigi, 0))); tEvent->SetStartTime(tFirstDigi->GetTime()); CbmTofDigiExp* tLastDigi = dynamic_cast(fTofDigis->At(tEvent->GetIndex(kTofDigi, tEvent->GetNofData(kTofDigi) - 1))); tEvent->SetEndTime(tLastDigi->GetTime()); } } } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- InitStatus CbmTofBuildMCEvents::Init() { // --- Get FairRootManager instance FairRootManager* ioman = FairRootManager::Instance(); assert ( ioman ); // --- Get input array (CbmTofDigiExp) fTofDigis = (TClonesArray*) ioman->GetObject("TofDigiExp"); assert ( fTofDigis ); // --- Get input array (CbmTofPoint) fTofPoints = (TClonesArray*) ioman->GetObject("TofPointTB"); if(fTofPoints) { fbPointsInTS = kTRUE; } // Register output array (CbmEvent) fEvents = new TClonesArray("CbmEvent",100); ioman->Register("Event", "CbmEvent", fEvents, IsOutputBranchPersistent("Event")); return kSUCCESS; } // --------------------------------------------------------------------------- ClassImp(CbmTofBuildMCEvents)