2727#include " CommonDataFormat/EvIndex.h"
2828#include " DetectorsCommonDataFormats/DetID.h"
2929#include " DataFormatsParameters/GRPObject.h"
30+ #include " DataFormatsCTP/Configuration.h"
3031#include " DataFormatsCTP/Digits.h"
3132#include " DataFormatsEMCAL/TriggerRecord.h"
33+ #include " DataFormatsFT0/Digit.h"
34+ #include " DataFormatsFV0/Digit.h"
3235
3336using namespace o2 ::framework;
3437using SubSpecificationType = o2::framework::DataAllocator::SubSpecificationType;
@@ -91,6 +94,77 @@ void DigitizerSpec::run(framework::ProcessingContext& ctx)
9194 TStopwatch timer;
9295 timer.Start ();
9396
97+ // Load FIT triggers if not running in self-triggered mode
98+ std::vector<o2::InteractionRecord> mbtriggers;
99+ if (mRequireCTPInput ) {
100+ // Hopefully at some point we can replace it by CTP input digits
101+ // In case of CTP digits react only to trigger inputs activated in trigger configuration
102+ // For the moment react to FIT vertex, cent and semicent triggers
103+ ctx.inputs ().get <o2::ctp::CTPConfiguration*>(" ctpconfig" );
104+ std::vector<uint64_t > inputmasks;
105+ for (const auto & trg : mCTPConfig ->getCTPClasses ()) {
106+ if (trg.cluster ->maskCluster [o2::detectors::DetID::EMC]) {
107+ // Class triggering EMCAL cluster
108+ LOG (debug) << " Found trigger class for EMCAL cluster: " << trg.name << " with input mask " << std::bitset<64 >(trg.descriptor ->getInputsMask ());
109+ inputmasks.emplace_back (trg.descriptor ->getInputsMask ());
110+ }
111+ }
112+ unsigned long ft0mask = 0 , fv0mask = 0 ;
113+ std::map<std::string, uint64_t > detInputName2Mask =
114+ {{" MVBA" , 1 }, {" MVOR" , 2 }, {" MVNC" , 4 }, {" MVCH" , 8 }, {" MVIR" , 0x10 }, {" MT0A" , 1 }, {" MT0C" , 2 }, {" MTSC" , 4 }, {" MTCE" , 8 }, {" MTVX" , 0x10 }};
115+ // Translation 2022: EMCAL cluster received CTP input masks, need to track it to FIT trigger masks
116+ std::map<std::string, std::pair<o2::detectors::DetID, std::string>> ctpInput2DetInput = {
117+ {" 0VBA" , {o2::detectors::DetID::FV0, " MVBA" }}, {" 0VOR" , {o2::detectors::DetID::FV0, " MVOR" }}, {" 0VNC" , {o2::detectors::DetID::FV0, " MVNC" }}, {" 0VCH" , {o2::detectors::DetID::FV0, " MVCH" }}, {" 0VIR" , {o2::detectors::DetID::FV0, " MVIR" }}, {" 0T0A" , {o2::detectors::DetID::FT0, " MT0A" }}, {" 0T0C" , {o2::detectors::DetID::FT0, " MT0C" }}, {" 0TSC" , {o2::detectors::DetID::FT0, " MTSC" }}, {" 0TCE" , {o2::detectors::DetID::FT0, " MTCE" }}, {" 0TVX" , {o2::detectors::DetID::FT0, " MTVX" }}};
118+ for (const auto & [det, ctpinputs] : mCTPConfig ->getDet2InputMap ()) {
119+ if (!(det == o2::detectors::DetID::FT0 || det == o2::detectors::DetID::FV0 || det == o2::detectors::DetID::CTP)) {
120+ continue ;
121+ }
122+ for (const auto & input : ctpinputs) {
123+ LOG (debug) << " CTP det input: " << input.name << " with mask " << std::bitset<64 >(input.inputMask );
124+ bool isSelected = false ;
125+ for (auto testmask : inputmasks) {
126+ if (testmask & input.inputMask ) {
127+ isSelected = true ;
128+ }
129+ }
130+ if (isSelected) {
131+ std::string usedInputName = input.name ;
132+ o2::detectors::DetID usedDetID = det;
133+ if (det == o2::detectors::DetID::CTP) {
134+ auto found = ctpInput2DetInput.find (input.name );
135+ if (found != ctpInput2DetInput.end ()) {
136+ usedInputName = found->second .second ;
137+ usedDetID = found->second .first ;
138+ LOG (debug) << " Decoded " << input.name << " -> " << usedInputName;
139+ }
140+ }
141+ auto maskFound = detInputName2Mask.find (usedInputName);
142+ if (maskFound != detInputName2Mask.end ()) {
143+ if (usedDetID == o2::detectors::DetID::FT0) {
144+ ft0mask |= maskFound->second ;
145+ } else {
146+ fv0mask |= maskFound->second ;
147+ }
148+ }
149+ }
150+ }
151+ }
152+ LOG (debug) << " FTO mask: " << std::bitset<64 >(ft0mask);
153+ LOG (debug) << " FVO mask: " << std::bitset<64 >(fv0mask);
154+ for (const auto & trg : ctx.inputs ().get <gsl::span<o2::ft0::DetTrigInput>>(" ft0inputs" )) {
155+ if (trg.mInputs .to_ulong () & ft0mask) {
156+ mbtriggers.emplace_back (trg.mIntRecord );
157+ }
158+ }
159+ for (const auto & trg : ctx.inputs ().get <gsl::span<o2::fv0::DetTrigInput>>(" fv0inputs" )) {
160+ if (trg.mInputs .to_ulong () & fv0mask) {
161+ if (std::find (mbtriggers.begin (), mbtriggers.end (), trg.mIntRecord ) == mbtriggers.end ()) {
162+ mbtriggers.emplace_back (trg.mIntRecord );
163+ }
164+ }
165+ }
166+ }
167+
94168 LOG (info) << " CALLING EMCAL DIGITIZATION " ;
95169 o2::dataformats::MCTruthContainer<o2::emcal::MCLabel> labelAccum;
96170
@@ -99,8 +173,13 @@ void DigitizerSpec::run(framework::ProcessingContext& ctx)
99173 // loop over all composite collisions given from context
100174 // (aka loop over all the interaction records)
101175 for (int collID = 0 ; collID < timesview.size (); ++collID) {
176+ bool trigger = true ; // Default: Self-triggered mode - all collisions treated as trigger
177+ if (mRequireCTPInput ) {
178+ // check if we have a trigger input from CTP
179+ trigger = (std::find (mbtriggers.begin (), mbtriggers.end (), timesview[collID]) != mbtriggers.end ());
180+ }
102181
103- mDigitizer .setEventTime (timesview[collID]);
182+ mDigitizer .setEventTime (timesview[collID], trigger );
104183
105184 if (!mDigitizer .isLive ()) {
106185 continue ;
@@ -180,9 +259,13 @@ void DigitizerSpec::finaliseCCDB(o2::framework::ConcreteDataMatcher& matcher, vo
180259 if (mCalibHandler ->finalizeCCDB (matcher, obj)) {
181260 return ;
182261 }
262+ if (matcher == o2::framework::ConcreteDataMatcher (" CTP" , " CTPCONFIG" , 0 )) {
263+ std::cout << " Loading CTP configuration" << std::endl;
264+ mCTPConfig = reinterpret_cast <o2::ctp::CTPConfiguration*>(obj);
265+ }
183266}
184267
185- o2::framework::DataProcessorSpec getEMCALDigitizerSpec (int channel, bool mctruth, bool useccdb)
268+ o2::framework::DataProcessorSpec getEMCALDigitizerSpec (int channel, bool requireCTPInput, bool mctruth, bool useccdb)
186269{
187270 // create the full data processor spec using
188271 // a name identifier
@@ -206,12 +289,17 @@ o2::framework::DataProcessorSpec getEMCALDigitizerSpec(int channel, bool mctruth
206289 calibloader->enableSimParams (true );
207290 calibloader->defineInputSpecs (inputs);
208291 }
292+ if (requireCTPInput) {
293+ inputs.emplace_back (" ft0inputs" , " FT0" , " TRIGGERINPUT" , 0 , Lifetime::Timeframe);
294+ inputs.emplace_back (" fv0inputs" , " FV0" , " TRIGGERINPUT" , 0 , Lifetime::Timeframe);
295+ inputs.emplace_back (" ctpconfig" , " CTP" , " CTPCONFIG" , 0 , Lifetime::Condition, ccdbParamSpec (" CTP/Config/Config" , true ));
296+ }
209297
210298 return DataProcessorSpec{
211299 " EMCALDigitizer" , // Inputs{InputSpec{"collisioncontext", "SIM", "COLLISIONCONTEXT", static_cast<SubSpecificationType>(channel), Lifetime::Timeframe}, InputSpec{"EMC_SimParam", o2::header::gDataOriginEMC, "SIMPARAM", 0, Lifetime::Condition, ccdbParamSpec("EMC/Config/SimParam")}},
212300 inputs,
213301 outputs,
214- AlgorithmSpec{o2::framework::adaptFromTask<DigitizerSpec>(calibloader)},
302+ AlgorithmSpec{o2::framework::adaptFromTask<DigitizerSpec>(calibloader, requireCTPInput )},
215303 Options{
216304 {" pileup" , VariantType::Int, 1 , {" whether to run in continuous time mode" }},
217305 {" debug-stream" , VariantType::Bool, false , {" Enable debug streaming" }}}
0 commit comments