@@ -166,13 +166,17 @@ void GenTPCLoopers::setGeomProtection(bool protect)
166166
167167bool GenTPCLoopers::ownsCollision (const std::vector<o2::steer::EventPart>& parts, int source)
168168{
169- // A collision is owned by the source with the lowest ID among the event parts it holds, so that
169+ // A collision is owned by the source with the highest ID among the event parts it holds, so that
170170 // exactly one of the simulations feeding a collision context (i.e. bkg, sgn) generates its loopers.
171- int lowest = std::numeric_limits<int >::max ();
171+ // The signal comes after the background and has one event per collision, so it tiles the time
172+ // exactly; a reused background event can only cover the average of its gaps. This assumes that
173+ // signal events are not reused. The rule only looks at the collision itself, because the
174+ // background reads the global context and each signal its per-timeframe one.
175+ int highest = std::numeric_limits<int >::min ();
172176 for (const auto & part : parts) {
173- lowest = std::min (lowest , part.sourceID );
177+ highest = std::max (highest , part.sourceID );
174178 }
175- return lowest == source;
179+ return highest == source;
176180}
177181
178182bool GenTPCLoopers::ownsContextCollisions ()
@@ -182,11 +186,11 @@ bool GenTPCLoopers::ownsContextCollisions()
182186 // simulation tiles the whole timeframe exactly once. When several transport simulations feed the
183187 // same context (embedding), each of them would tile that same time axis again and the loopers
184188 // would end up in the digits as many times as there are simulations.
185- // Every collision is therefore owned by exactly one source, the one with the lowest source ID
189+ // Every collision is therefore owned by exactly one source, the one with the highest source ID
186190 // among the event parts present, and only the owner generates loopers for it. Embedding without
187- // replacement ("@" patterns) leaves all collisions to the background, since its event part is
188- // present everywhere ; when the signal replaces the background ("r" patterns) the background part
189- // is taken out of the collisions it loses, so each source covers exactly its own share .
191+ // replacement ("@" patterns) gives the signal the collisions it is embedded into and the
192+ // background the others ; when the signal replaces the background ("r" patterns) each source
193+ // owns the collisions it is present in alone .
190194 const auto & simConfig = o2::conf::SimConfig::Instance ();
191195 const auto contextAndPrefix = simConfig.getCollContextFilenameAndEventPrefix ();
192196 const std::string contextName = contextAndPrefix.first .empty () ? " collisioncontext.root" : contextAndPrefix.first ;
@@ -202,9 +206,12 @@ bool GenTPCLoopers::ownsContextCollisions()
202206 }
203207 const auto source = context->findSimPrefix (simPrefix);
204208 if (source < 0 ) {
209+ if (context->getSimPrefixes ().size () <= 1 ) {
210+ return true ; // a single source: nobody to share the loopers with
211+ }
205212 LOG (warn) << " Simulation prefix " << simPrefix << " not found in the collision context " << contextName
206- << " ; loopers will be generated without checking for other sources" ;
207- return true ;
213+ << " , which is shared by " << context-> getSimPrefixes (). size () << " sources; loopers will remain OFF " ;
214+ return false ;
208215 }
209216 // count the collisions this source takes part in and those it owns
210217 unsigned int nPresent = 0 , nOwned = 0 ;
0 commit comments