Skip to content

Commit bf44138

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 5dbdd62 commit bf44138

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
@@ -107,12 +107,112 @@ bool generateEvent() override
107107
return true;
108108
}
109109

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

117217
/// Generate mNumSigEvs HF events to be merged in one
118218
int nEvsHF = 0;
@@ -124,22 +224,126 @@ Bool_t importParticles() override
124224
genOk = (mGeneratorEvHF->generateEvent() && mGeneratorEvHF->importParticles() /*copy particles from mGeneratorEvHF.mPythia.event to mGeneratorEvHF.mParticles*/ );
125225
}
126226

227+
int originalSize = mParticles.size(); // stack of this event generator
228+
229+
// for debug
230+
// LOG(info) << "";
231+
// LOG(info) << "============ Before HF event " << nEvsHF;
232+
// LOG(info) << "Full stack (size " << originalSize << "):";
233+
// printParticleVector(mParticles);
234+
127235
/// copy the particles from the HF event in the particle stack
128236
auto particlesHfEvent = mGeneratorEvHF->getParticles();
129-
int originalSize = mParticles.size(); // stack of this event generator
237+
std::map<int, int /*particle id in HF event stack*/> mapHfParticles = {};
238+
int counterHfParticles = 0;
239+
240+
// for debug
241+
// LOG(info) << "-----------------------------------------------";
242+
// LOG(info) << ">>> HF event " << nEvsHF;
243+
// LOG(info) << " HF event stack:";
244+
// printParticleVector(particlesHfEvent);
245+
130246
for(int iPart=0; iPart<particlesHfEvent.size(); iPart++) {
131247
auto particle = particlesHfEvent.at(iPart);
132248

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

139336
/// copy inside this.mParticles from mGeneratorEvHF.mParticles, i.e. the particles generated in mGeneratorEvHF
140337
mParticles.push_back(particle);
338+
141339
}
142340

341+
// for debug
342+
// LOG(info) << "-----------------------------------------------";
343+
// LOG(info) << "============ After HF event " << nEvsHF;
344+
// LOG(info) << "Full stack:";
345+
// printParticleVector(mParticles);
346+
143347
/// one more event generated, let's update the counter and clear it, to allow the next generation
144348
nEvsHF++;
145349
//mGeneratedEvents++;

0 commit comments

Comments
 (0)