Skip to content

Commit 6210c7e

Browse files
mfagginMattia Faggin
authored andcommitted
PWGHF: development to embed in Pb-Pb bkg event only HF particles from pp events (#1716)
* Development to embed in Pb-Pb bkg event only HF particles from pp events. * Further fixes on mother/daughter re-indexing. * Comment out debug LOG(info) and further cleaning. * Removing comment lines. * Clean further obsolete comment. --------- Co-authored-by: Mattia Faggin <mfaggin@alipap1.cern.ch> (cherry picked from commit f919a51)
1 parent cffc138 commit 6210c7e

File tree

1 file changed

+209
-5
lines changed

1 file changed

+209
-5
lines changed

MC/config/PWGHF/external/generator/generator_pythia8_embed_hf.C

Lines changed: 209 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,112 @@ bool generateEvent() override
121121
return true;
122122
}
123123

124+
/// @brief Main function to find out whether the particle comes charm or beauty quark
125+
/// @param partId is the index of the particle under study
126+
/// @param particles are the particles of the full event
127+
bool isFromCharmOrBeauty(const int partId, std::vector<TParticle> const& particles) {
128+
129+
// Let's check wheter this is already a c or b quark?
130+
const TParticle& part = particles.at(partId);
131+
const int pdgAbs = std::abs(part.GetPdgCode());
132+
if(pdgAbs == 4 || pdgAbs == 5) {
133+
return true;
134+
}
135+
136+
// Let's check the mother particles of the hadron at all stages
137+
// and look for the charm or beauty quark
138+
std::vector<std::vector<int64_t>> arrayIds{};
139+
std::vector<int64_t> initVec{partId};
140+
arrayIds.push_back(initVec); // the first vector contains the index of the original particle
141+
int stage = 0;
142+
while(arrayIds[-stage].size() > 0) {
143+
144+
//LOG(info) << "### stage " << stage << ", arrayIds[-stage].size() = " << arrayIds[-stage].size();
145+
146+
std::vector<int64_t> arrayIdsStage{};
147+
148+
for (auto& iPart : arrayIds[-stage]) { // check all the particles that were the mothers at the previous stage
149+
const TParticle& partStage = particles.at(iPart);
150+
151+
// check the first mother
152+
const int firstMotherId = partStage.GetFirstMother();
153+
if( firstMotherId >= 0) {
154+
const TParticle& firstMother = particles.at(firstMotherId);
155+
const int pdgAbsFirstMother = std::abs(firstMother.GetPdgCode());
156+
if(pdgAbsFirstMother == 4 || pdgAbsFirstMother == 5) {
157+
return true;
158+
}
159+
// the first mother is not a charm or beauty quark
160+
arrayIdsStage.push_back(firstMotherId);
161+
}
162+
163+
// let's check all other mothers, if any
164+
const int lastMotherId = partStage.GetSecondMother();
165+
if(lastMotherId >=0 && lastMotherId != firstMotherId) {
166+
for(int motherId = firstMotherId+1 /*first mother already considered*/; motherId <= lastMotherId; motherId++) {
167+
const TParticle& mother = particles.at(motherId);
168+
const int pdgAbsMother = std::abs(mother.GetPdgCode());
169+
if(pdgAbsMother == 4 || pdgAbsMother == 5) {
170+
return true;
171+
}
172+
// this mother is not a charm or beauty quark
173+
arrayIdsStage.push_back(motherId);
174+
}
175+
}
176+
177+
}
178+
179+
/*
180+
All light-flavour mothers are not considered with this approach
181+
eg: D+ coming from c and uBar --> uBar lost
182+
--> TODO: check if the current particle has a charm or beauty hadron as daughter. If yes, keep it
183+
>>> we can ignore it! This might be useful only for jet analyses, however this approach of embedding N pp events into a Pb-Pb one might be not ideal for them
184+
*/
185+
186+
// none of the particle mothers is a charm or beauty quark, let's consider their indices for the next stage
187+
arrayIds.push_back(arrayIdsStage);
188+
stage--; // ready to go to next stage
189+
190+
} /// end while(arrayIds[-stage].size() > 0)
191+
192+
return false;
193+
}
194+
195+
196+
void printParticleVector(std::vector<TParticle> v) {
197+
for(int id=0; id<v.size(); id++) {
198+
const int pdgCode = v.at(id).GetPdgCode();
199+
const int idFirstMother = v.at(id).GetFirstMother();
200+
const int idLastMother = v.at(id).GetSecondMother();
201+
const int idFirstDaughter = v.at(id).GetFirstDaughter();
202+
const int idLastDaughter = v.at(id).GetLastDaughter();
203+
LOG(info) << " id = " << id << ", pdgCode = " << pdgCode << " --> idFirstMother=" << idFirstMother << ", idLastMother=" << idLastMother << ", idFirstDaughter=" << idFirstDaughter << ", idLastDaughter=" << idLastDaughter;
204+
}
205+
}
206+
207+
208+
int findKey(const std::map<int, int /*index*/>& m, int value) {
209+
for(std::pair<int, int> p : m) {
210+
if(p.second /*index*/ == value) {
211+
return p.first; // key --> it becomes the new index
212+
}
213+
}
214+
return -1;
215+
}
216+
217+
124218
/// @brief Main function to copy the generated particles in mPythia.event into the stack (this.mParticles)
125219
Bool_t importParticles() override
126220
{
127221
/// Import particles from generated event
128222
/// This should not do anything now, since we override generateEvent
129223
GeneratorPythia8::importParticles();
224+
225+
LOG(info) << "";
226+
LOG(info) << "*************************************************************";
227+
LOG(info) << "************** New signal event considered **************";
228+
LOG(info) << "*************************************************************";
229+
LOG(info) << "";
130230

131231
/// Generate mNumSigEvs HF events to be merged in one
132232
int nEvsHF = 0;
@@ -138,22 +238,126 @@ Bool_t importParticles() override
138238
genOk = (mGeneratorEvHF->generateEvent() && mGeneratorEvHF->importParticles() /*copy particles from mGeneratorEvHF.mPythia.event to mGeneratorEvHF.mParticles*/ );
139239
}
140240

241+
int originalSize = mParticles.size(); // stack of this event generator
242+
243+
// for debug
244+
// LOG(info) << "";
245+
// LOG(info) << "============ Before HF event " << nEvsHF;
246+
// LOG(info) << "Full stack (size " << originalSize << "):";
247+
// printParticleVector(mParticles);
248+
141249
/// copy the particles from the HF event in the particle stack
142250
auto particlesHfEvent = mGeneratorEvHF->getParticles();
143-
int originalSize = mParticles.size(); // stack of this event generator
251+
std::map<int, int /*particle id in HF event stack*/> mapHfParticles = {};
252+
int counterHfParticles = 0;
253+
254+
// for debug
255+
// LOG(info) << "-----------------------------------------------";
256+
// LOG(info) << ">>> HF event " << nEvsHF;
257+
// LOG(info) << " HF event stack:";
258+
// printParticleVector(particlesHfEvent);
259+
144260
for(int iPart=0; iPart<particlesHfEvent.size(); iPart++) {
145261
auto particle = particlesHfEvent.at(iPart);
146262

263+
/// Establish if this particle comes from charm or beauty
264+
/// If not, ignore this particle and increase the number of discarded particles from the pp event
265+
if(!isFromCharmOrBeauty(iPart, particlesHfEvent)) {
266+
continue;
267+
}
268+
/// if we arrive here, then the current particle is from charm or beauty, keep it!
269+
mapHfParticles[counterHfParticles++/*fill and update the counter*/] = iPart;
270+
}
271+
272+
/// print the map (debug)
273+
// LOG(info) << " >>>";
274+
// LOG(info) << " >>> printing mapHfParticles:";
275+
// for(auto& p : mapHfParticles) {
276+
// const int pdgCodeFromMap = particlesHfEvent.at(p.second).GetPdgCode();
277+
// LOG(info) << " >>> entry " << p.first << ", original id = " << p.second << ", pdgCode=" << pdgCodeFromMap << " --> firstMotherId=" << particlesHfEvent.at(p.second).GetFirstMother() << ", lastMotherId=" << particlesHfEvent.at(p.second).GetSecondMother() << ", firstDaughterId=" << particlesHfEvent.at(p.second).GetFirstDaughter() << ", lastDaughterId=" << particlesHfEvent.at(p.second).GetLastDaughter();
278+
// }
279+
280+
281+
// In the map we have only the particles from charm or beauty
282+
// Let's readapt the mother/daughter indices accordingly
283+
int offset = originalSize;
284+
for(int iHfPart=0; iHfPart<counterHfParticles; iHfPart++) {
285+
TParticle& particle = particlesHfEvent.at(mapHfParticles[iHfPart]);
286+
int idFirstMother = particle.GetFirstMother(); // NB: indices from the HF event stack
287+
int idLastMother = particle.GetSecondMother(); // NB: indices from the HF event stack
288+
int idFirstDaughter = particle.GetFirstDaughter(); // NB: indices from the HF event stack
289+
int idLastDaughter = particle.GetLastDaughter(); // NB: indices from the HF event stack
290+
const int pdgCode = particle.GetPdgCode();
291+
292+
/// fix mother indices
293+
bool isFirstMotherOk = false;
294+
const int idFirstMotherOrig = idFirstMother; /// useful only if the 1st mother is not charm or beauty
295+
if(idFirstMother >= 0) {
296+
idFirstMother = findKey(mapHfParticles, idFirstMother);
297+
/// If idFirstMother>=0, the 1st mother is from charm or beauty, i.e. is not a light-flavoured parton
298+
/// Instead, if idFirstMother==-1 from findKey this means that the first mother was a light-flavoured parton --> not stored in the map
299+
if(idFirstMother >=0) {
300+
/// the 1st mother is from charm or beauty, i.e. is not a light-flavoured parton
301+
if(idLastMother != idFirstMotherOrig) {
302+
if(idLastMother != -1) {
303+
/// idLastMother is >= 0
304+
}
305+
} else {
306+
/// idLastMother is equal to idFirstMother
307+
idLastMother = idFirstMother;
308+
}
309+
isFirstMotherOk = true;
310+
}
311+
}
312+
if(!isFirstMotherOk) {
313+
/// - If we are here, it means that the 1st mother was not from charm or beauty
314+
/// - No need to check whether idLastMother>=0,
315+
/// because this would mean that none of the mother is from charm or beauty and this was checked already in isFromCharmOrBeauty
316+
/// - Need to loop between 1st and last mother, to treat cases like these
317+
/// [11:52:13][INFO] id = 565, pdgCode = -2 --> idFirstMother=519, idLastMother=519
318+
/// [11:52:13][INFO] id = 566, pdgCode = -4 --> idFirstMother=520, idLastMother=520
319+
/// [11:52:13][INFO] id = 567, pdgCode = -1 --> idFirstMother=518, idLastMother=518
320+
/// [11:52:13][INFO] id = 568, pdgCode = -311 --> idFirstMother=565, idLastMother=567
321+
/// [11:52:13][INFO] id = 569, pdgCode = -4212 --> idFirstMother=565, idLastMother=567
322+
/// --> w/o loop between 1st and last mother, the mother Ids assigned to this Sc+ (4212) by findKey are -1, both first and last
323+
bool foundAnyMother = false;
324+
for(int idMotherOrig=(idFirstMotherOrig+1); idMotherOrig<=idLastMother; idMotherOrig++) {
325+
const int idMother = findKey(mapHfParticles, idMotherOrig);
326+
if(idMother >= 0) {
327+
/// this should mean that the mother is from HF, i.e. that we found the correct one
328+
idFirstMother = idMother;
329+
idLastMother = idFirstMother;
330+
foundAnyMother = true;
331+
break;
332+
}
333+
}
334+
// set last mother to -1 if no mother has been found so far
335+
if (!foundAnyMother) {
336+
idLastMother = -1;
337+
}
338+
}
339+
340+
/// fix daughter indices
341+
idFirstDaughter = findKey(mapHfParticles, idFirstDaughter);
342+
idLastDaughter = findKey(mapHfParticles, idLastDaughter);
343+
147344
/// adjust the particle mother and daughter indices
148-
if(particle.GetFirstMother() >= 0) particle.SetFirstMother(particle.GetFirstMother() + originalSize);
149-
if(particle.GetSecondMother() >= 0) particle.SetLastMother(particle.GetSecondMother() + originalSize);
150-
if(particle.GetFirstDaughter() >= 0) particle.SetFirstDaughter(particle.GetFirstDaughter() + originalSize);
151-
if(particle.GetLastDaughter() >= 0) particle.SetLastDaughter(particle.GetLastDaughter() + originalSize);
345+
particle.SetFirstMother((idFirstMother >= 0) ? idFirstMother + offset : idFirstMother);
346+
particle.SetLastMother((idLastMother >= 0) ? idLastMother + offset : idLastMother);
347+
particle.SetFirstDaughter((idFirstDaughter >= 0) ? idFirstDaughter + offset : idFirstDaughter);
348+
particle.SetLastDaughter((idLastDaughter >= 0) ? idLastDaughter + offset : idLastDaughter);
152349

153350
/// copy inside this.mParticles from mGeneratorEvHF.mParticles, i.e. the particles generated in mGeneratorEvHF
154351
mParticles.push_back(particle);
352+
155353
}
156354

355+
// for debug
356+
// LOG(info) << "-----------------------------------------------";
357+
// LOG(info) << "============ After HF event " << nEvsHF;
358+
// LOG(info) << "Full stack:";
359+
// printParticleVector(mParticles);
360+
157361
/// one more event generated, let's update the counter and clear it, to allow the next generation
158362
nEvsHF++;
159363
//mGeneratedEvents++;

0 commit comments

Comments
 (0)