@@ -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,42 @@ 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+ bool triggered = Generator::triggerEvent ();
426+ if (!triggered) {
427+ // counter is decreased when event is rejected, otherwise simulation hangs
428+ // when using trigger mechanism. If no trigger is used all events are
429+ // automatically accepted
430+ mEventCounter --;
431+ }
375432 if (mEventCounter == mNEvents ) {
376433 LOG (info) << " HybridGen: Stopping TBB task pool" ;
377434 mStopFlag = true ;
378435 }
379-
380- return true ;
436+ return triggered;
381437}
382438
383439void GeneratorHybrid::updateHeader (o2::dataformats::MCEventHeader* eventHeader)
@@ -485,6 +541,32 @@ Bool_t GeneratorHybrid::parseJSON(const std::string& path)
485541 }
486542 }
487543
544+ // check if there is a trigger field, if not the trigger mode is set to OFF
545+ // unless a generator has a trigger mode specified, in this case it will be forced to OR during the initialization
546+ // TODO: make the triggering options more versatile
547+ if (doc.HasMember (" trigger" )) {
548+ const auto & trigger = doc[" trigger" ].GetString ();
549+ if (strcmp (trigger, " or" ) == 0 ) {
550+ // OR
551+ LOG (info) << " Setting trigger mode to OR" ;
552+ setTriggerMode (o2::eventgen::Generator::kTriggerOR );
553+ } else if (strcmp (trigger, " and" ) == 0 ) {
554+ // AND
555+ LOG (info) << " Setting trigger mode to AND" ;
556+ setTriggerMode (o2::eventgen::Generator::kTriggerAND );
557+ } else if (strcmp (trigger, " off" ) == 0 ) {
558+ LOG (warn) << " Trigger OFF" ;
559+ } else if (strlen (trigger) == 0 ) {
560+ // OFF by default
561+ LOG (warn) << " Trigger mode not specified, turning to OR if gen list has a trigger mode specified" ;
562+ mTriggerFlag = false ;
563+ } else {
564+ // OFF by default
565+ LOG (warn) << " Unknown trigger mode, turning to OR if gen list has a trigger mode specified (otherwise OFF)" ;
566+ mTriggerFlag = false ;
567+ }
568+ }
569+
488570 // Put the generator names in mInputGens
489571 if (doc.HasMember (" generators" )) {
490572 const auto & gens = doc[" generators" ];
0 commit comments