From 9c5e59bd2e6fc516b686960d0124edf15eb920bb Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Mon, 26 Jul 2021 14:37:10 +0200 Subject: [PATCH] [EMCAL-704] Add suport of cell container in multiple subtimeframes In case the reconstruction runs on the FLP the cells might come from two different cell containers from the two subtimeframes. In this case the cell containers might not be merged, but instead the TriggerRecords are merged to have two different RangeReferences with a subspecification, called Subevent. The event loop iterates over the CombinedEvent containing the interaction record, the trigger type and the list of subevents. In order to identify the cell container based on the subspecification a map is built at the beginning of the monitorData function. --- Modules/EMCAL/include/EMCAL/DigitsQcTask.h | 23 +++ Modules/EMCAL/src/DigitsQcTask.cxx | 155 +++++++++++++++------ 2 files changed, 134 insertions(+), 44 deletions(-) diff --git a/Modules/EMCAL/include/EMCAL/DigitsQcTask.h b/Modules/EMCAL/include/EMCAL/DigitsQcTask.h index a442b635ec..0a6f02247b 100644 --- a/Modules/EMCAL/include/EMCAL/DigitsQcTask.h +++ b/Modules/EMCAL/include/EMCAL/DigitsQcTask.h @@ -19,8 +19,13 @@ #include "QualityControl/TaskInterface.h" #include +#include +#include #include #include +#include "CommonDataFormat/InteractionRecord.h" +#include "CommonDataFormat/RangeReference.h" +#include "DataFormatsEMCAL/TriggerRecord.h" class TH1; class TH2; @@ -89,6 +94,24 @@ class DigitsQcTask final : public TaskInterface void setEndOfPayloadCheck(Bool_t doCheck) { mDoEndOfPayloadCheck = doCheck; } private: + struct SubEvent { + int mSpecification; + dataformats::RangeReference mCellRange; + }; + struct CombinedEvent { + InteractionRecord mInteractionRecord; + uint32_t mTriggerType; + std::vector mSubevents; + + int getNumberOfObjects() const + { + int nObjects = 0; + for (auto ev : mSubevents) + nObjects += ev.mCellRange.getEntries(); + return nObjects; + } + }; + std::vector buildCombinedEvents(const std::unordered_map>& triggerrecords) const; void startPublishing(DigitsHistograms& histos); Double_t mCellThreshold = 0.5; ///< energy cell threshold Bool_t mDoEndOfPayloadCheck = false; ///< Do old style end-of-payload check diff --git a/Modules/EMCAL/src/DigitsQcTask.cxx b/Modules/EMCAL/src/DigitsQcTask.cxx index 41978f6032..d0fb7afa8a 100644 --- a/Modules/EMCAL/src/DigitsQcTask.cxx +++ b/Modules/EMCAL/src/DigitsQcTask.cxx @@ -27,7 +27,11 @@ #include "EMCALBase/Geometry.h" #include "EMCALCalib/BadChannelMap.h" #include "EMCALCalib/TimeCalibrationParams.h" +#include +#include +#include #include +#include #include namespace o2 @@ -98,22 +102,36 @@ void DigitsQcTask::monitorData(o2::framework::ProcessingContext& ctx) } } - // Get payload and loop over digits - auto digitcontainer = ctx.inputs().get>("emcal-digits"); //it was emcal::Digit - auto triggerrecords = ctx.inputs().get>("emcal-triggerecords"); + // Handling of inputs from multiple subevents (multiple FLPs) + // Build maps of trigger records and cells according to the subspecification + // and combine trigger records from different maps into a single map of range + // references and subspecifications + std::vector cellInputs{ { "cellfilter", framework::ConcreteDataTypeMatcher(header::gDataOriginEMC, "CELLS") } }, + triggerRecordInputs{ { "triggerrecordfilter", framework::ConcreteDataTypeMatcher(header::gDataOriginEMC, "CELLSTRGR") } }; + std::unordered_map> cellSubEvents; + std::unordered_map> triggerRecordSubevents; + + for (const auto& celldata : framework::InputRecordWalker(ctx.inputs(), cellInputs)) { + int subspecification = framework::DataRefUtils::getHeader(celldata)->subSpecification; + cellSubEvents[subspecification] = ctx.inputs().get>(celldata); + } + for (const auto& trgrecorddata : framework::InputRecordWalker(ctx.inputs(), triggerRecordInputs)) { + int subspecification = framework::DataRefUtils::getHeader(trgrecorddata)->subSpecification; + triggerRecordSubevents[subspecification] = ctx.inputs().get>(trgrecorddata); + } + + auto combinedEvents = buildCombinedEvents(triggerRecordSubevents); // QcInfoLogger::GetInstance() << "Received " << digitcontainer.size() << " digits " << AliceO2::InfoLogger::InfoLogger::endm; int eventcounter = 0; - for (auto trg : triggerrecords) { + for (auto trg : combinedEvents) { if (!trg.getNumberOfObjects()) { continue; } - QcInfoLogger::GetInstance() << QcInfoLogger::Debug << "Next event " << eventcounter << " has " << trg.getNumberOfObjects() << " digits" << QcInfoLogger::endm; - gsl::span eventdigits(digitcontainer.data() + trg.getFirstEntry(), trg.getNumberOfObjects()); //trigger type - auto triggertype = trg.getTriggerBits(); + auto triggertype = trg.mTriggerType; bool isPhysTrigger = triggertype & o2::trigger::PhT, isCalibTrigger = triggertype & o2::trigger::Cal; std::string trgClass; if (isPhysTrigger) { @@ -127,44 +145,53 @@ void DigitsQcTask::monitorData(o2::framework::ProcessingContext& ctx) auto histos = mHistogramContainer[trgClass]; - for (auto digit : eventdigits) { - int index = digit.getHighGain() ? 0 : (digit.getLowGain() ? 1 : -1); - if (index < 0) - continue; - auto cellindices = mGeometry->GetCellIndex(digit.getTower()); - - histos.mDigitAmplitude[index]->Fill(digit.getEnergy(), digit.getTower()); - - auto timeoffset = mTimeCalib ? mTimeCalib->getTimeCalibParam(digit.getTower(), digit.getLowGain()) : 0.; - - if (!mBadChannelMap || (mBadChannelMap->getChannelStatus(digit.getTower()) == MaskType_t::GOOD_CELL)) { - histos.mDigitAmplitudeCalib[index]->Fill(digit.getEnergy(), digit.getTower()); - histos.mDigitTimeCalib[index]->Fill(digit.getTimeStamp() - timeoffset, digit.getTower()); - } - histos.mDigitTime[index]->Fill(digit.getTimeStamp(), digit.getTower()); - - // get the supermodule for filling EMCAL/DCAL spectra - - try { - - auto [row, col] = mGeometry->GlobalRowColFromIndex(digit.getTower()); - if (digit.getEnergy() > 0) { - histos.mDigitOccupancy->Fill(col, row); + // iterate over subevents + for (auto& subev : trg.mSubevents) { + auto cellsSubspec = cellSubEvents.find(subev.mSpecification); + if (cellsSubspec == cellSubEvents.end()) { + QcInfoLogger::GetInstance() << QcInfoLogger::Error << "No cell data found for subspecification " << subev.mSpecification << QcInfoLogger::endm; + } else { + gsl::span eventdigits(cellsSubspec->second.data() + subev.mCellRange.getFirstEntry(), subev.mCellRange.getEntries()); + for (auto digit : eventdigits) { + int index = digit.getHighGain() ? 0 : (digit.getLowGain() ? 1 : -1); + if (index < 0) + continue; + auto cellindices = mGeometry->GetCellIndex(digit.getTower()); + histos.mDigitAmplitude[index]->Fill(digit.getEnergy(), digit.getTower()); + + auto timeoffset = mTimeCalib ? mTimeCalib->getTimeCalibParam(digit.getTower(), digit.getLowGain()) : 0.; + + if (!mBadChannelMap || (mBadChannelMap->getChannelStatus(digit.getTower()) == MaskType_t::GOOD_CELL)) { + histos.mDigitAmplitudeCalib[index]->Fill(digit.getEnergy(), digit.getTower()); + histos.mDigitTimeCalib[index]->Fill(digit.getTimeStamp() - timeoffset, digit.getTower()); + } + histos.mDigitTime[index]->Fill(digit.getTimeStamp(), digit.getTower()); + + // get the supermodule for filling EMCAL/DCAL spectra + + try { + + auto [row, col] = mGeometry->GlobalRowColFromIndex(digit.getTower()); + if (digit.getEnergy() > 0) { + histos.mDigitOccupancy->Fill(col, row); + } + if (digit.getEnergy() > mCellThreshold) { + histos.mDigitOccupancyThr->Fill(col, row); + } + histos.mIntegratedOccupancy->Fill(col, row, digit.getEnergy()); + + if (std::get<0>(cellindices) < 12) + histos.mDigitAmplitudeEMCAL->Fill(digit.getEnergy()); + + else + histos.mDigitAmplitudeDCAL->Fill(digit.getEnergy()); + } catch (o2::emcal::InvalidCellIDException& e) { + QcInfoLogger::GetInstance() << "Invalid cell ID: " << e.getCellID() << AliceO2::InfoLogger::InfoLogger::endm; + }; } - if (digit.getEnergy() > mCellThreshold) { - histos.mDigitOccupancyThr->Fill(col, row); - } - histos.mIntegratedOccupancy->Fill(col, row, digit.getEnergy()); - - if (std::get<0>(cellindices) < 12) - histos.mDigitAmplitudeEMCAL->Fill(digit.getEnergy()); - - else - histos.mDigitAmplitudeDCAL->Fill(digit.getEnergy()); - } catch (o2::emcal::InvalidCellIDException& e) { - QcInfoLogger::GetInstance() << "Invalid cell ID: " << e.getCellID() << AliceO2::InfoLogger::InfoLogger::endm; - }; + } } + histos.mnumberEvents->Fill(1); eventcounter++; } @@ -190,22 +217,62 @@ void DigitsQcTask::reset() } } +std::vector DigitsQcTask::buildCombinedEvents(const std::unordered_map>& triggerrecords) const +{ + std::vector events; + + // Search interaction records from all subevents + std::set allInteractions; + for (auto& [subspecification, trgrec] : triggerrecords) { + for (auto rec : trgrec) { + auto eventIR = rec.getBCData(); + if (allInteractions.find(eventIR) == allInteractions.end()) + allInteractions.insert(eventIR); + } + } + + // iterate over all subevents for all bunch crossings + for (auto collision : allInteractions) { + CombinedEvent nextevent; + nextevent.mInteractionRecord = collision; + bool first = true, + hasSubevent = false; + for (auto [subspecification, records] : triggerrecords) { + auto found = std::find_if(records.begin(), records.end(), [&collision](const o2::emcal::TriggerRecord& rec) { return rec.getBCData() == collision; }); + if (found != records.end()) { + hasSubevent = true; + if (first) { + nextevent.mTriggerType = found->getTriggerBits(); + first = false; + } + nextevent.mSubevents.push_back({ subspecification, o2::dataformats::RangeReference(found->getFirstEntry(), found->getNumberOfObjects()) }); + } + } + if (hasSubevent) + events.emplace_back(nextevent); + } + return events; +} + void DigitsQcTask::startPublishing(DigitsHistograms& histos) { for (auto h : histos.mDigitAmplitude) { getObjectsManager()->startPublishing(h); } + /* for (auto h : histos.mDigitTime) { getObjectsManager()->startPublishing(h); } + */ for (auto h : histos.mDigitAmplitudeCalib) { getObjectsManager()->startPublishing(h); } - + /* for (auto h : histos.mDigitTimeCalib) { getObjectsManager()->startPublishing(h); } + */ getObjectsManager()->startPublishing(histos.mDigitAmplitudeEMCAL); getObjectsManager()->startPublishing(histos.mDigitAmplitudeDCAL);