@@ -183,6 +183,14 @@ Bool_t GeneratorHybrid::Init()
183183 }
184184 gens[count]->Init (); // TODO: move this to multi-threaded
185185 addSubGenerator (count, gen);
186+ // If trigger mode is an unknown value or empty string in the JSON file, it will be set to kTriggerOR
187+ // when at least one generator has trigger mode enabled. If the trigger field is not set then trigger is forced OFF
188+ if (!mTriggerFlag && gens[count]->getTriggerMode ()) {
189+ LOG (info) << " Generator " << gen << " has trigger mode enabled to " << gens[count]->getTriggerMode ();
190+ LOG (info) << " Setting Hybrid trigger mode to OR" ;
191+ setTriggerMode (o2::eventgen::Generator::kTriggerOR );
192+ mTriggerFlag = true ;
193+ }
186194 count++;
187195 }
188196 if (mRandomize ) {
@@ -349,6 +357,13 @@ bool GeneratorHybrid::importParticles()
349357 // Clear particles and event header
350358 mParticles .clear ();
351359 mMCEventHeader .clearInfo ();
360+
361+ // Clear trigger information of previous generator
362+ mInterface = nullptr ;
363+ mInterfaceName = " " ;
364+ mDeepTriggers .clear ();
365+ mTriggers .clear ();
366+
352367 if (mCocktailMode ) {
353368 // in cocktail mode we need to merge the particles from the different generators
354369 for (auto subIndex : subGenIndex) {
@@ -357,6 +372,23 @@ bool GeneratorHybrid::importParticles()
357372 mParticles .insert (mParticles .end (), subParticles.begin (), subParticles.end ());
358373 // fetch the event Header information from the underlying generator
359374 gens[subIndex]->updateHeader (&mMCEventHeader );
375+ // Trigger forwarding to hybrid gen for the event
376+ // For cocktail mode only the first generator in the list is used for triggers
377+ // TODO: implement trigger merging for cocktail mode
378+ if (strcmp (mInterfaceName .c_str (), " " ) == 0 ) {
379+ if (gens[subIndex]->getTriggers ().size () > 0 ) {
380+ for (auto & Trigger : gens[subIndex]->getTriggers ()) {
381+ addTrigger (Trigger);
382+ }
383+ }
384+ if (gens[subIndex]->getDeepTriggers ().size () > 0 ) {
385+ for (auto & deepTrigger : gens[subIndex]->getDeepTriggers ()) {
386+ addDeepTrigger (deepTrigger);
387+ }
388+ }
389+ mInterface = gens[subIndex]->getInterface ();
390+ mInterfaceName = gens[subIndex]->getInterfaceName ();
391+ }
360392 mInputTaskQueue .push (subIndex);
361393 mTasksStarted ++;
362394 }
@@ -366,18 +398,43 @@ bool GeneratorHybrid::importParticles()
366398 mParticles = gens[genIndex]->getParticles ();
367399 // fetch the event Header information from the underlying generator
368400 gens[genIndex]->updateHeader (&mMCEventHeader );
401+ // Trigger forwarding to hybrid gen for the event
402+ if (gens[genIndex]->getTriggers ().size () > 0 ) {
403+ for (auto & Trigger : gens[genIndex]->getTriggers ()) {
404+ addTrigger (Trigger);
405+ }
406+ }
407+ if (gens[genIndex]->getDeepTriggers ().size () > 0 ) {
408+ for (auto & deepTrigger : gens[genIndex]->getDeepTriggers ()) {
409+ addDeepTrigger (deepTrigger);
410+ }
411+ }
412+ mInterface = gens[genIndex]->getInterface ();
413+ mInterfaceName = gens[genIndex]->getInterfaceName ();
369414 mInputTaskQueue .push (genIndex);
370415 mTasksStarted ++;
371416 }
372417
373418 mseqCounter++;
374419 mEventCounter ++;
420+
421+ return true ;
422+ }
423+
424+ bool GeneratorHybrid::triggerEvent ()
425+ {
426+ bool triggered = Generator::triggerEvent ();
427+ if (!triggered) {
428+ // counter is decreased when event is rejected, otherwise simulation hangs
429+ // when using trigger mechanism. If no trigger is used all events are
430+ // automatically accepted
431+ mEventCounter --;
432+ }
375433 if (mEventCounter == mNEvents ) {
376434 LOG (info) << " HybridGen: Stopping TBB task pool" ;
377435 mStopFlag = true ;
378436 }
379-
380- return true ;
437+ return triggered;
381438}
382439
383440void GeneratorHybrid::updateHeader (o2::dataformats::MCEventHeader* eventHeader)
@@ -485,6 +542,32 @@ Bool_t GeneratorHybrid::parseJSON(const std::string& path)
485542 }
486543 }
487544
545+ // check if there is a trigger field, if not the trigger mode is set to OFF
546+ // unless a generator has a trigger mode specified, in this case it will be forced to OR during the initialization
547+ // TODO: make the triggering options more versatile
548+ if (doc.HasMember (" trigger" )) {
549+ const auto & trigger = doc[" trigger" ].GetString ();
550+ if (strcmp (trigger, " or" ) == 0 ) {
551+ // OR
552+ LOG (info) << " Setting trigger mode to OR" ;
553+ setTriggerMode (o2::eventgen::Generator::kTriggerOR );
554+ } else if (strcmp (trigger, " and" ) == 0 ) {
555+ // AND
556+ LOG (info) << " Setting trigger mode to AND" ;
557+ setTriggerMode (o2::eventgen::Generator::kTriggerAND );
558+ } else if (strcmp (trigger, " off" ) == 0 ) {
559+ LOG (warn) << " Trigger OFF" ;
560+ } else if (strlen (trigger) == 0 ) {
561+ // OFF by default
562+ LOG (warn) << " Trigger mode not specified, turning to OR if gen list has a trigger mode specified" ;
563+ mTriggerFlag = false ;
564+ } else {
565+ // OFF by default
566+ LOG (warn) << " Unknown trigger mode, turning to OR if gen list has a trigger mode specified (otherwise OFF)" ;
567+ mTriggerFlag = false ;
568+ }
569+ }
570+
488571 // Put the generator names in mInputGens
489572 if (doc.HasMember (" generators" )) {
490573 const auto & gens = doc[" generators" ];
0 commit comments